Référence : Expressions JQ pour les adaptateurs Digital Twin
Modèles d'expression JQ pratiques pour les entrées de périphérique, les enveloppes d'adaptateur, les conditions de routage et les mappages de charge utile pour normaliser la télémétrie dans ce qui est défini dans les modèles jumeaux numériques.
Concepts clés
Vous pouvez écrire des expressions JQ dans un adaptateur jumeau numérique en tant que paramètres fictifs ${ ... } pour calculer les valeurs cibles dans payload-mapping et évaluer les conditions de routage.
Méthodes courantes pour utiliser des expressions JQ :
- Entrée de l'appareil : Données utiles brutes publiées par les appareils.
- Enveloppe : Déclare des points d'extrémité de référence et des exemples de formes de données utiles. Par exemple, vous pouvez définir un mappage
timeObserved. - Routes : Évaluez les conditions, notamment les points d'extrémité, les en-têtes, le corps, et sélectionnez un mappage de données utiles.
- Mappages de données utiles : Transformer, convertir des unités, renommer des clés et normaliser le schéma de modèle DTDL.
- Sortie : Sortie JSON normalisée qui doit satisfaire à la validation du modèle jumeau numérique, y compris les types, les intervalles et les unités.
- Prise en charge des fonctions de mappage : Les fonctions arithmétiques et
floorsont acceptées. Les fonctions telles quetoIntegeretnumberne sont pas prises en charge. - Correspondance de point d'extrémité : Utilise des conditions basées sur des segments avec
endpoint(n), par exemple :${endpoint(1) == 'home' and endpoint(2) == 'sonnen' and endpoint(3) == 'status'}au lieu de modèles génériques non pris en charge. - Entier par rapport au schéma double :
- Pour
schema: "integer", assurez-vous que votre mappage émet des chiffres intégraux (par exemple,"${(.velocity_kph / 1.609) | floor}"). - Pour
schema: "double", les sorties fractionnaires sont acceptées; utilisezflooruniquement si vous voulez un stockage en nombre entier comme double, par exemple 68.0.
- Pour
- Type de conversion flexible : Les chaînes de type numérique et les doubles en nombres entiers sont acceptées lorsqu'elles correspondent au type de modèle (par exemple, un entier). Les assistants de moulage tels que
number()ettoIntegerne sont pas pris en charge dans les expressions de routage; utilisez arithmétique etfloor, ou adoptezschema: "double"pour conserver les fractions.- Pass-through (mph, schéma "integer") :
{"speed": "60"}et{"speed": 60.0}sont stockés en tant que60.{"speed": "60.2"}est rejeté sauf si le mappage est forcé à un entier, par exemple, avecfloor. - Route de mesure (kph → mph) :
{"velocity_kph": 110}→68;{"velocity_kph": "110"}→68car le mappagefloorémet un nombre entier. Gardez les entrées arithmétiques numériques pour éviter les erreurs d'expression; préférez110à"110"dans la mesure du possible. - L'arrondissement reste explicite : La conversion temporaire n'arrondit pas automatiquement
68.35à68. Utilisezfloorpour le schéma entier ou passez au modèleschema: "double"pour conserver les fractions.
- Pass-through (mph, schéma "integer") :
- Traitement des enveloppes et du temps : Si
timeObservedn'est pas fourni, la plate-forme peut utiliserreceivedTime. Utilisezfromdateformat,todateformatet les fonctions connexes pour les conversions de temps dans les mappages d'enveloppe ou de données utiles.
La validation des données est effectuée par rapport à votre modèle DTDL. Si une propriété est déclarée en tant que
integer, la sortie normalisée doit être une valeur integer, et non string ou float. Voir le modèle de correction d'entier ci-dessous.Pour plus d'informations, voir Informations de référence sur l'extension de validation DTMI.
Exemples d'entrée d'appareil
Données utiles entrantes typiques avec des schémas spécifiques à l'unité :
Unités américaines standard miles par heure :
{
"speed": 60
}Unités métriques européennes en kilomètres par heure :
{
"velocity_kph": 110
}
Charge utile imbriquée à partir d'un capteur :
{
"telemetry": { "temp_c": 22.4, "humidity": 48 }
}
Tableau d'échantillons :
{
"samples": [ { "kph": 30 }, { "kph": 50 }, { "kph": 0 } ]
}Ces exemples montrent un modèle DTDL où la température est un nombre entier compris entre 0 et 100 et l'humidité est facultative.
{ "temperature": 60, "humidity": 45 }{
"humidity": 45
}{
“temperature”: null
“humidity”: 45
}Mappage d'enveloppe
envelope.json déclare une valeur referenceEndpoint et une valeur referencePayload. Facultativement, un mappage d'enveloppe peut définir time-observed :
{
"referenceEndpoint": "telemetry/automotive/standard",
"referencePayload": {
"dataFormat": "JSON",
"data": { "speed": 65 }
}
}
L'identificateur spécial
receivedTime peut être fourni par la plate-forme lorsque l'appareil omet time. Si le mappage d'enveloppe est spécifié et contient une valeur timeObserved, receivedTime est utilisé en tant que valeur timeObserved. Modèles de condition de routage
Les conditions de routage sont des règles ou expressions utilisées pour déterminer quelle règle de mappage ou de traitement doit être appliquée à un message ou à une demande entrant. Si une condition de routage est vraie, la règle de mappage ou de transformation associée est déclenchée et appliquée.
Dans cet exemple, la condition de routage de l'adaptateur jumeau numérique définit deux routes pour le traitement des messages d'appareil entrants, en fonction du format des données, par exemple si des unités de mesure sont reçues sur le 3e segment du chemin du point d'extrémité, /vehicle/speed/metric-units/, puis
[
{
"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)sélectionne le segment de cheminn-th(basé sur 0 ou 1 selon l'adaptateur). Dans le scénario de normalisation des unités de mesure,endpoint(3)est utilisé pour que/vehicle/speed/metric-units/corresponde au troisième segmentmetric-units.- Placez des conditions plus spécifiques avant le
"*"catch-all. payloadMapping:- Prend le champ
velocity_kphvitesse en kilomètres par heure de la charge utile, et le convertit en miles par heure :.velocity_kph / 1.609 - Applique
floorpour arrondir à l'entier inférieur le plus prochefloorn'est pas lancé. Le résultat peut donc être un nombre à virgule flottante. - Le résultat est affecté au champ de sortie
speed.
- Prend le champ
referencePayload:- Indique l'entrée attendue pour cette route :
{"velocity_kph": 104}
- Indique l'entrée attendue pour cette route :
- Point d'extrémité d'entrée :
/vehicle/speed/metric-units/device123 - Données utiles d'entrée :
{ "velocity_kph": 104 }Mappage de sortie :{ "speed": 64 } (since 104 / 1.609 = 64.64, floor is 64)
Exemples de mappage de données utiles
Expressions JQ communes pour les mappages de données utiles :
- Transmission directe :
"$.speed": "$.speed" - Renommer la clé :
"$.speed": "${.velocity_kph}" - Conversion d'unité :
"$.mph": "${.kph / 1.609}" - Plancher/plafond/rond :
"${.x | floor}","${.x | ceil}","${.x | round}" - Coalesce/par défaut (dépendant de la version) :
"${ if .value? then .value else 0 end }" - Conversion de type :
- À numéro :
"${.value | tonumber}"(prend en chargetonumberdans la plupart des versions) - À la chaîne :
"${.value | tostring}"
Note
Dans un adaptateur jumeau numérique IoT, les fonctions de casting telles quetoIntegerounumberne sont pas acceptées dansinbound-routes. Vous pouvez utiliser l'arithmétique avecfloordéfini pour un schéma entier ou utiliserschema: "double"et les formats d'arrondissement pour l'ingestion de données en aval.inbound-routesdoit être un format JSON valide; les expressions appartiennent aux chaînes entre guillemets"${ ... }". - À numéro :
- Extraction imbriquée :
"${.telemetry.temp_c}" - Mappage de tableau :
"${[ .samples[] | .kph / 1.609 | floor ]}" - Conditionnel :
"${ if .kph > 0 then .kph / 1.609 else 0 end }"
Selon l'intégration de votre adaptateur, les expressions entre guillemets
"${...}" peuvent être sérialisées en tant que chaînes. Lorsque le moteur prend en charge les expressions sans guillemets, par exemple ${...} en tant que valeur brute, il est recommandé que le formulaire émette un nombre JSON plutôt qu'une chaîne.Nuances : Types d'entiers, chaînes et nombres calculés
Lorsqu'une propriété DTDL est schema: "integer", la sortie normalisée doit être de type entier. Deux modes de défaillance courants lors du calcul des valeurs :
- Stringification : Une expression encapsulée entre guillemets peut générer
"68"(chaîne), échec de la validation d'entiers. - Nombres de type flottant : L'arithmétique produit
68.0; certains valideurs traitent cela comme un non-entier, même s'il est mathématiquement intégral.
Corriger les modèles :
- Utiliser l'étage seulement pour le schéma de nombres entiers :
"${(.velocity_kph / 1.609) | floor}"pour produire une valeur numérique intégrale qui satisfait le type de nombre entier. - Autre : Remplacez la propriété de modèle par
schema: "double"pour conserver la précision fractionnelle, ou appliquezfloorau mappage tout en stockant un nombre entier en tant que double. Arrondir/formater dans APEX/SQL, si nécessaire.
Exemples de mappage d'adaptateur de jumeau numérique
Cet exemple normalise les kilomètres par heure (KPH) en miles par heure (MPH) à l'aide de floor (pas de distribution).
{
"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 }
}
}
Exemple : Passage par rattrapage par défaut
{
"description": "English units passthrough.",
"condition": "*",
"payloadMapping": {
"$.speed": "$.speed"
}
}
Exemple : télémétrie imbriquée et coalescence par défaut
{
"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 }"
}
}
Exemple : normalisation d'un tableau
{
"description": "Normalize kph samples to mph (whole-number mph via floor).",
"condition": "${.samples?}",
"payload-mapping": {
"$.speeds": "${ [ .samples[] | .kph / 1.609 | floor ] }"
}
}
Attentes de sortie par rapport à la validation de modèle
Les sorties doivent satisfaire les schémas et contraintes du modèle jumeau numérique. Pour le modèle d'unité automobile dans model.json, voir Scénario : Normalisation des unités de mesure à l'aide d'un adaptateur de jumeau numérique :
name:speedschema:integerunit:milePerHourminimum:0,maximum:100
speed normalisé doit être un nombre entier compris dans 0,100. La validation d'une chaîne calculée "68" ou d'un nombre à virgule flottante 68.0 échouera.
Limites et conseils
- La disponibilité du filtre varie : Filtres jq les plus importants (
floor,ceil,round,tonumber,tostring,map,select,add) - Type émission : Les expressions intégrées dans des chaînes entre guillemets peuvent sérialiser en tant que chaînes. Préférez les expressions brutes sans guillemets si elles sont prises en charge pour émettre des types numériques.
- Traitement nul : Les opérations sur
nullpeuvent produirenull. Utilisezif .x? then ... else ... endpour les valeurs par défaut. - Précision : L'arithmétique de point flottant peut introduire des artefacts d'arrondissement; appliquez
roundetfloorselon les besoins avant le moulage. - Entier coulé : Dans les tests observés,
toIntegeretnumbern'ont pas été acceptés dansinbound-routeslors de la création de l'adaptateur. Préférez arithmétique +floorpour le schéma entier ou utilisezschema: "double"et arrondissez le format en aval.
Application du correctif de nombre entier au scénario automobile
Le scénario crée un modèle avec un nombre entier speed et achemine les données utiles d'unité de mesure vers le même modèle jumeau numérique. Sans casting explicite, la valeur calculée peut être rejetée par validation en raison de la dérive de type (chaîne ou nombre flottant).
Correctif utilisé dans le scénario :
"$.speed": "${(.velocity_kph / 1.609) | floor}"
Pourquoi il est nécessaire :
- Le plancher garantit que la valeur est entièrement numérique, d'après le type de nombre entier.
- Alternative : utilisez
schema: "double"pour préserver la précision fractionnaire et arrondir et formater en aval si nécessaire.
Lors de l'utilisation d'un schéma entier, préférez arithmétique plus
floor. Pour le double schéma, vous pouvez omettre floor pour conserver le MPH fractionnaire ou l'inclure pour stocker un nombre entier MPH en tant que double.Extraits de référence rapides
Exemples pris en charge :
- Condition : Correspondance de point d'extrémité :
"condition": "${endpoint(3) == \"metric-units\"}" - Mappage : Transfert :
"$.speed": "$.speed" - Mappage : kph → mph (schéma entier) :
"$.speed": "${(.kph / 1.609) | floor}" - Mappage : imbriqué :
"$.room_temp_c": "${.telemetry.temp_c}" - Mappage : Par défaut :
"$.value": "${ if .value? then .value else 0 end }" - Transformation Tableau :
"$.list": "${ [ .arr[] | .x | tonumber ] }"
Comportement des nombres entiers par rapport aux modèles doubles
La présente section résume l'incidence du type de schéma de modèle sur le mappage et la validation des adaptateurs.
- schéma : "entier"
- Type : Doit être un nombre entier JSON intégral. Les chaînes telles que
68ou les résultats de type flottant68.0peuvent échouer la validation des nombres entiers. - Mappage : L'arithmétique est autorisée;
floorest pris en charge. Les fonctions telles quetoIntegeretnumberne sont pas prises en charge. - Modèle : Utilisez
"${(.velocity_kph / 1.609) | floor}"pour forcer l'intégration de MPH. Cette validation et cette télémétrie réussies ont été acceptéesHTTP 202. - Intervalle : Les valeurs minimale et maximale sont appliquées, par exemple
0–100
- Type : Doit être un nombre entier JSON intégral. Les chaînes telles que
schema: "double"- Type : Tout nombre entier ou fractionnaire JSON est accepté dans l'intervalle; aucun arrondissement automatique n'est effectué par la plate-forme.
- Mappage : Vous pouvez conserver la précision fractionnelle, par exemple
"${.velocity_kph / 1.609}", ou appliquer égalementfloorpour produire un nombre entier MPH stocké en tant que double, par exemple :68.0 - Intervalle : S'il est défini, minimum et maximum appliqués, par exemple :
0–100
Résultats de télémétrie observés
Les combinaisons suivantes ont été validées de bout en bout (HTTP/1.1 202 Accepted) :
- Modèle entier + mappage d'étage :
"${(.velocity_kph / 1.609) | floor}"→ accepté - Modèle double + mappage brut :
"${.velocity_kph / 1.609}"→ mph fractionnaire accepté - Mappage double modèle + plancher :
"${(.velocity_kph / 1.609) | floor}"→ nombre entier mph accepté et stocké en tant que double
Exemple de boucle (paramètres fictifs)
Modèle double, valeur brute qui est fractionnaire mi/h comme prévu :
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 }'
Double modèle, plancher un nombre entier MPH, qui est stocké comme double :
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 }'
Réponse HTTP attendue pour chaque cas :
HTTP/1.1 202 Accepted
content-type: text/plain
Accepted
En aval dans APEX ou considérations SQL
- Avec le double, la vitesse fractionnelle est conservée. Utilisez SQL
FLOOR/ROUNDpour l'affichage des nombres entiers :SELECT FLOOR(speed) AS speed_mph FROM ... - Avec un entier, assurez-vous que le mappage retourne des valeurs intégrales (par exemple, au moyen de
floor) pour satisfaire la validation.
Nom d'utilisateur et devis de l'autorisation
Dans OCI IoT, l'utilisation du nom d'utilisateur d'authentification de base est égale à l'instance external-key. Si l'instance est créée avec des guillemets intégrés dans la clé externe, ces guillemets font partie du nom d'utilisateur requis et doivent être envoyés littéralement. Cela provoque souvent des problèmes de citation de shell.
Meilleure pratique : Créez des instances de jumeau numérique avec des clés externes qui ne contiennent pas de guillemets. Par exemple, american-auto Lorsque vous devez vous authentifier avec des noms d'utilisateur entre guillemets, créez un en-tête Authorization: Basic ... au lieu d'utiliser -u pour éviter les erreurs de soumission.