Riferimento: Espressioni JQ per adattatori gemelli digitali

Modelli di espressione JQ pratici per gli input del dispositivo, gli involucri dell'adattatore, le condizioni di instradamento e i mapping del payload per normalizzare la telemetria in ciò che è definito nei modelli gemelli digitali.

Concetti chiave

È possibile scrivere espressioni JQ all'interno di un adattatore digital twin come segnaposto ${ ... } per calcolare i valori di destinazione in payload-mapping e per valutare le condizioni di instradamento.

Modi comuni per utilizzare le espressioni JQ:

  • Input dispositivo: payload raw inviati dai dispositivi.
  • Sviluppo: dichiara gli endpoint di riferimento e le forme di payload di esempio, ad esempio è possibile definire il mapping timeObserved.
  • Cicli: valuta le condizioni, inclusi endpoint, intestazioni, corpo e seleziona un mapping di payload.
  • Mapping payload: trasforma, converte unità, rinomina chiavi e normalizza nello schema del modello DTDL.
  • Output: output JSON normalizzato che deve soddisfare la convalida del modello gemello digitale, inclusi tipi, intervalli, unità.
  • Supporto delle funzioni di mapping: le funzioni aritmetica e floor sono accettate. Funzioni quali toInteger e number non sono supportate.
  • Corrispondenza endpoint: utilizza condizioni basate su segmenti con endpoint(n), ad esempio: ${endpoint(1) == 'home' and endpoint(2) == 'sonnen' and endpoint(3) == 'status'} anziché pattern con caratteri jolly non supportati.
  • Confronto tra intero e doppio schema:
    • Per schema: "integer", assicurarsi che il mapping emetta numeri integrali (ad esempio, "${(.velocity_kph / 1.609) | floor}").
    • Per schema: "double", vengono accettati output frazionari. Utilizzare floor solo se si desidera che lo storage con numeri interi sia doppio, ad esempio 68.0.
  • Tipo di conversione soft: le stringhe di tipo numerico e le doppie con numeri interi vengono accettate quando corrispondono al tipo di modello (ad esempio, numero intero). Gli aiutanti di casting come number() e toInteger rimangono non supportati nelle espressioni di instradamento; si basano sull'aritmetica e su floor o adottano schema: "double" per preservare le frazioni.
    • Pass-through (mph, schema "integer"): {"speed": "60"} e {"speed": 60.0} vengono memorizzati come 60. {"speed": "60.2"} viene rifiutato a meno che il mapping delle coercizioni a un numero intero, ad esempio, con floor.
    • Instradamento metrica (kph → mph): {"velocity_kph": 110}68; {"velocity_kph": "110"}68 perché il mapping floor emette un numero intero. Mantenere gli input aritmetici numerici per evitare errori di espressione; preferire 110 rispetto a "110", se possibile.
    • L'arrotondamento rimane esplicito: la conversione flessibile non arrotonda automaticamente 68.35 a 68. Usare floor per lo schema di numeri interi oppure passare al modello schema: "double" per conservare le frazioni.
  • Gestione di buste e tempi: se non viene fornito timeObserved, la piattaforma può utilizzare receivedTime. Utilizzare fromdateformat, todateformat e le funzioni correlate per le conversioni temporali nei mapping di buste o payload.
Nota

La convalida dei dati viene eseguita in base al modello DTDL. Se una proprietà viene dichiarata come integer, l'output normalizzato deve essere un valore integer, non un valore string o float. Vedere il pattern di correzione numero intero riportato di seguito.

Per ulteriori informazioni, vedere Informazioni di riferimento sull'estensione per la convalida DMI

Esempi di input dispositivo

Payload in entrata tipici con schemi specifici dell'unità:

Unità standard USA miglia all'ora:

{
  "speed": 60
}

Unità metriche europee chilometri all'ora:

{
  "velocity_kph": 110
}

Payload nidificato da un sensore:

{
  "telemetry": { "temp_c": 22.4, "humidity": 48 }
}

Array di campioni:

{
  "samples": [ { "kph": 30 }, { "kph": 50 }, { "kph": 0 } ]
}

Questi esempi mostrano un modello DTDL in cui la temperatura è un numero intero compreso tra 0 e 100 e l'umidità è facoltativa.

Quando entrambi i valori sono presenti e la temperatura è compresa nell'intervallo consentito e del tipo corretto, è valida e viene incluso l'intero valore di input:
{ "temperature": 60, "humidity": 45 }
Quando un valore è assegnato, vengono inclusi solo i dati validi. In questo esempio manca la temperatura, quindi l'umidità viene ingerita e il valore della temperatura non viene aggiornato.
{
"humidity": 45
}
Quando un valore è nullo, viene ignorato e viene incluso solo il valore valido:
{
		“temperature”: null
 		“humidity”: 45
	}

Mapping buste

envelope.json dichiara un referenceEndpoint e un referencePayload. Facoltativamente, un mapping di buste può impostare time-observed:

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

L'identificativo speciale receivedTime può essere fornito dalla piattaforma quando il dispositivo omette time. Se il mapping dell'envelope viene specificato e contiene un valore timeObserved, receivedTime viene utilizzato come valore timeObserved.

Pattern delle condizioni di instradamento

Le condizioni di instradamento sono regole o espressioni utilizzate per determinare quale regola di mapping o elaborazione deve essere applicata a un messaggio o a una richiesta in entrata. Se una condizione di instradamento restituisce true, la regola di mapping o trasformazione associata viene attivata e applicata.

In questo esempio, la condizione di instradamento digital twin adapter definisce due instradamenti per l'elaborazione dei messaggi dispositivo in entrata, in base al formato dei dati, ad esempio se vengono ricevute unità di metrica nel 3° segmento del percorso endpoint, /vehicle/speed/metric-units/ quindi

[
  {
    "description": "European metric to mph; convert then floor (no explicit cast).",
    "condition": "${endpoint(3) == \"metric-units\"}",
    "payloadMapping": {
      "$.speed": "${(.velocity_kph / 1.609) | floor}"
    },
    "referencePayload": {
      "dataFormat": "JSON",
      "data": { "velocity_kph": 104 }
    }
  },
  {
    "description": "USA standard units passthrough.",
    "condition": "*",
    "payloadMapping": { "$.speed": "$.speed" }
  }
]
  • endpoint(n) seleziona il segmento di percorso n-th (basato su 0 o 1 a seconda dell'adattatore). Nello scenario di normalizzazione delle unità di misura, viene utilizzato endpoint(3) in modo che /vehicle/speed/metric-units/ corrisponda al terzo segmento metric-units.
  • Porre condizioni più specifiche prima del "*" catch-all.
  • payloadMapping:
    • Prende la velocità del campo velocity_kph in chilometri all'ora dal payload e la converte in miglia all'ora: .velocity_kph / 1.609
    • Applica floor per arrotondare al numero intero più vicino floor non cast, pertanto il risultato potrebbe essere un float.
    • Il risultato viene assegnato al campo di output speed.
  • referencePayload:
    • Dimostra l'input previsto per questo instradamento: {"velocity_kph": 104}
  • Endpoint di input: /vehicle/speed/metric-units/device123
  • Payload di input: { "velocity_kph": 104 } Mapping di output: { "speed": 64 } (since 104 / 1.609 = 64.64, floor is 64)

Esempi di mapping dei payload

Espressioni JQ comuni per i mapping del payload:

  • Pass-through: "$.speed": "$.speed"
  • Rinomina chiave: "$.speed": "${.velocity_kph}"
  • Conversione unità: "$.mph": "${.kph / 1.609}"
  • Pavimento/soffitto/rotondo: "${.x | floor}", "${.x | ceil}", "${.x | round}"
  • Coalesce/default (dipendente dalla versione): "${ if .value? then .value else 0 end }"
  • Conversione del tipo:
    • Al numero: "${.value | tonumber}" (supporta tonumber nella maggior parte delle build)
    • Stringa - A: "${.value | tostring}"
    Nota

    In un IoT adattatore gemello digitale, le funzioni di fusione come toInteger o number non sono accettate in inbound-routes. È possibile utilizzare l'aritmetica con floor definito per uno schema con numeri interi oppure utilizzare i formati schema: "double" e di arrotondamento per l'inclusione dei dati a valle. inbound-routes deve essere un JSON valido; le espressioni appartengono alle stringhe tra virgolette "${ ... }".
  • Estrazione nidificata: "${.telemetry.temp_c}"
  • Mappa array: "${[ .samples[] | .kph / 1.609 | floor ]}"
  • Condizionale: "${ if .kph > 0 then .kph / 1.609 else 0 end }"
Nota

A seconda dell'integrazione dell'adattatore, le espressioni all'interno delle virgolette "${...}" possono essere serializzate come stringhe. Quando il motore supporta ad esempio espressioni senza virgolette, ${...} come valore raw, è consigliabile che il modulo emetta un numero JSON anziché una stringa.

Nuances: tipi di numeri interi, stringhe e numeri calcolati

Se la proprietà DTDL è schema: "integer", l'output normalizzato deve essere di tipo intero. Due modalità comuni di errore durante il calcolo dei valori:

  1. Stringificazione: un'espressione racchiusa tra virgolette può generare "68" (stringa), errore durante la convalida degli interi.
  2. Numero a virgola mobile: l'aritmetica produce 68.0; alcuni convalidatori la considerano come un numero non intero, anche se matematicamente integrale.

Correggi pattern:

  • Usa solo piano per lo schema con numeri interi: "${(.velocity_kph / 1.609) | floor}" per produrre un numero integrale che soddisfi la digitazione di numeri interi.
  • Alternativa: consente di impostare la proprietà del modello su schema: "double" per mantenere la precisione frazionaria oppure applicare floor nel mapping durante la memorizzazione di un numero intero come doppio. Arrotonda/formatta in APEX/SQL in base alle esigenze.

Esempi di mappatura dell'adattatore Digital Twin

Questo esempio normalizza chilometri all'ora (KPH) in miglia all'ora (MPH) utilizzando floor (senza cast).

{
  "description": "European auto uses metric units; convert to mph and floor to whole number.",
  "condition": "${endpoint(3) == \"metric-units\"}",
  "payloadMapping": {
    "$.speed": "${(.velocity_kph / 1.609) | floor}"
  },
  "referencePayload": {
    "dataFormat": "JSON",
    "data": { "velocity_kph": 104 }
  }
}

Esempio: pass-through catch-all predefinito

{
  "description": "English units passthrough.",
  "condition": "*",
  "payloadMapping": {
    "$.speed": "$.speed"
  }
}

Esempio: telemetria nidificata e impostazione predefinita di coalesce

{
  "description": "Extract nested temp; default to 0 when missing.",
  "condition": "${endpoint(2) == \"env\"}",
  "payload-mapping": {
    "$.room_temp_c": "${ if .telemetry.temp_c? then .telemetry.temp_c else 0 end }"
  }
}

Esempio: normalizzazione degli array

{
  "description": "Normalize kph samples to mph (whole-number mph via floor).",
  "condition": "${.samples?}",
  "payload-mapping": {
    "$.speeds": "${ [ .samples[] | .kph / 1.609 | floor ] }"
  }
}

Aspettative dell'output rispetto alla convalida del modello

Gli output devono soddisfare schemi e vincoli del modello gemello digitale. Per il modello di unità per il settore automobilistico in model.json, vedere Scenario: normalizzazione delle unità di misura mediante un adattatore Digital Twin:

  • name: speed
  • schema: integer
  • unit: milePerHour
  • minimum: 0, maximum: 100

speed normalizzato deve essere un numero intero all'interno di 0,100. Una stringa calcolata "68" o un numero a virgola mobile 68.0 non riuscirà a eseguire la convalida.

Limitazioni e suggerimenti

  • La disponibilità dei filtri varia: la maggior parte dei filtri jq di base (floor, ceil, round, tonumber, tostring, map, select, add)
  • Emissione tipo: le espressioni incorporate nelle stringhe tra virgolette possono essere serializzate come stringhe. Preferire le espressioni senza virgolette raw se supportate per l'emissione di tipi numerici.
  • Gestione nulla: le operazioni su null possono produrre null. Utilizzare if .x? then ... else ... end per le impostazioni predefinite difensive.
  • Precisione: l'aritmetica a virgola mobile può introdurre artifact di arrotondamento; applicare round e floor in base alle esigenze prima della fusione.
  • Integer cast: nei test osservati, toInteger e number non sono stati accettati in inbound-routes al momento della creazione dell'adattatore. Preferire l'aritmetica + floor per lo schema con numeri interi oppure utilizzare schema: "double" e arrotondare il formato a valle.

Applicazione della correzione numero intero allo scenario automobilistico

Lo scenario crea un modello con un numero intero speed e instrada i payload dell'unità metrica allo stesso modello gemello digitale. Senza un cast esplicito, il valore calcolato può essere rifiutato dalla convalida a causa della deviazione del tipo (stringa o numero a virgola mobile).

Correzione utilizzata nello scenario:

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

Perché è necessario:

  • floor garantisce che il valore sia di tipo numero intero soddisfacente.
  • Alternativa: utilizzare schema: "double" per mantenere la precisione frazionaria e arrotondare e formattare a valle, se necessario.
Nota

Quando si utilizza uno schema con numeri interi, si preferisce aritmetica più floor. Per il doppio schema, è possibile omettere floor per mantenere MPH frazionario o includerlo per memorizzare un numero intero MPH come doppio.

Frammenti di riferimento rapidi

Esempi supportati:

  • Condizione: corrispondenza endpoint: "condition": "${endpoint(3) == \"metric-units\"}"
  • Mapping: pass-through: "$.speed": "$.speed"
  • Mapping: kph → mph (schema intero): "$.speed": "${(.kph / 1.609) | floor}"
  • Mapping: nidificato: "$.room_temp_c": "${.telemetry.temp_c}"
  • Mapping: predefinito: "$.value": "${ if .value? then .value else 0 end }"
  • Trasformazione dell'array: "$.list": "${ [ .arr[] | .x | tonumber ] }"

Comportamento modello intero/doppio

In questa sezione viene descritto come il tipo di schema del modello influisce sul mapping e sulla convalida dell'adattatore.

  • schema: "integer"
    • Tipo: deve essere un numero JSON intero integrale. Le stringhe come 68 o i risultati a virgola mobile 68.0 possono non riuscire nella convalida dei numeri interi.
    • Mapping: l'aritmetica è consentita; floor è supportato. Funzioni quali toInteger e number non sono supportate.
    • Pattern: utilizzare "${(.velocity_kph / 1.609) | floor}" per forzare a MPH integrale. Il componente aggiuntivo ha superato il processo di validazione e telemetria HTTP 202.
    • Intervallo: vengono applicati i valori minimo e massimo, ad esempio 0–100
  • schema: "double"
    • Tipo: qualsiasi numero JSON integrato o frazionario viene accettato se compreso nell'intervallo; nessun arrotondamento automatico eseguito dalla piattaforma.
    • Mapping: è possibile preservare la precisione frazionaria, ad esempio "${.velocity_kph / 1.609}", oppure applicare anche floor per produrre un numero intero MPH memorizzato come doppio, ad esempio 68.0
    • Intervallo: se definito, minimo e massimo applicati, ad esempio: 0–100

Risultati telemetria osservati

Le seguenti combinazioni sono state convalidate end-to-end (HTTP/1.1 202 Accepted):

  • Modello intero + mappatura del pavimento: "${(.velocity_kph / 1.609) | floor}" → accettato
  • Modello doppio + mapping raw: "${.velocity_kph / 1.609}" → mph frazionario accettato
  • Mapping doppio modello + pavimento: "${(.velocity_kph / 1.609) | floor}" → numero intero mph accettato e memorizzato come doppio

Curl di esempio (placeholder)

Doppio modello, valore raw che è mph frazionario come previsto:

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

Doppio modello, pavimento un numero intero MPH, che è memorizzato come doppio:

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

Risposta HTTP prevista per ciascun caso:

HTTP/1.1 202 Accepted
content-type: text/plain

Accepted

Considerazioni a valle in APEX o SQL

  • Con il comando double la velocità frazionaria viene mantenuta. Utilizzare SQL FLOOR/ROUND per la visualizzazione dei numeri interi:
    SELECT FLOOR(speed) AS speed_mph FROM ...
  • Con integer, assicurarsi che il mapping generi valori integrali (ad esempio, tramite floor) per soddisfare la convalida.

Nome utente e preventivi autorizzazione

In OCI IoT, l'uso del nome utente di autenticazione Basic equivale all'istanza external-key. Se l'istanza viene creata con virgolette incorporate nella chiave esterna, tali virgolette diventano parte del nome utente richiesto e devono essere inviate letteralmente. Questo spesso causa problemi di citazione delle shell.

Procedura ottimale: creare istanze digital twin con chiavi esterne che non includono virgolette, ad esempio american-auto Quando è necessario eseguire l'autenticazione con nomi utente tra virgolette, creare un'intestazione Authorization: Basic ... anziché utilizzare -u per evitare errori di citazione.