Scénario : Normalisation des unités de mesure à l'aide d'un adaptateur Digital Twin
Ce scénario explique comment utiliser un modèle de jumeau numérique, un adaptateur jumeau numérique avec des mappages d'enveloppe et de route pour normaliser une télémétrie spécifique dans un schéma commun, et comment valider le flux en reportant des données utiles d'échantillons de périphériques.
Ce scénario montre comment publier des données de télémétrie automobile avec différentes unités de mesure en milles par heure et en kilomètres par heure à l'aide de différents points d'extrémité, de deux instances de jumeau numérique et de deux clés externes différentes. Pour plus d'informations sur les modèles JQ référencés dans ce scénario, voir Référence : Expressions JQ pour les adaptateurs de jumeaux numériques.
Un adaptateur jumeau numérique achemine les demandes par point d'extrémité et cale les données utiles vers un seul modèle. Par exemple, un modèle de mesure envoie une vitesse en kilomètres par heure (velocity_kph) tandis qu'une autre instance de jumeau numérique standard envoie des milles par heure (speed).
Tâches
- Comprendre les fichiers inclus dans ce scénario
- Créer un modèle de jumeau numérique
- Créer un adaptateur jumeau numérique avec enveloppe et itinéraires
- Créer deux instances de jumeau numérique
- Envoyer un exemple de télémétrie pour valider le routage et le mappage
- Vérifier le comportement de la normalisation
Avant de commencer
Assurez-vous que vous disposez des autorisations requises et que votre interface de ligne de commande OCI est configurée. Pour plus d'informations, voir Préalables, Informations détaillées sur les politiques pour la plate-forme Internet of Things (IoT) et Utilisation d'un fichier JSON pour une entrée complexe.
Comprenez les fichiers de ce scénario :
Extraits de code que vous pouvez utiliser dans votre modèle de jumeau numérique référencé dans les étapes ci-dessous :
model.json— Modèle jumeau numérique basé sur les spécifications DTDL v3 avec une propriété de télémétriespeeden milles par heure qui utilise une extension de validation qui applique des limites sur l'intervalle de valeurs de 0 à 100.envelope.json— Configuration d'enveloppe qui déclare un point d'extrémité de référence et un exemple de forme de données utiles.routes.json— Conditions d'acheminement et mappages de charge utile qui convertissent les kilomètres par heure en milles par heure.script.sh— Dans cet exemple, vous pouvez enregistrer toutes les commandes de l'interface de ligne de commande OCI répertoriées ci-dessous pour créer un modèle, un adaptateur et des instances de jumeau numérique, plus les commandescurlpour effectuer l'auto-test de démarrage (POST) et l'exécuter en tant que script d'interpréteur de commandesscript.sh.Pour effectuer les étapes de ce scénario, vous pouvez créer et enregistrer l'interface de ligne de commande OCI et les commandes
curllistées dans les étapes ci-dessous et exécuter ce scénario en tant que script d'interpréteur de commandes :script.sh
Cet exemple d'extrait de code de modèle de jumeau numérique model.json utilise une extension personnalisée dtmi:com:oracle:dtdl:extension:validation;1 qui applique des règles de validation au schéma JSON pour les éléments "Telemetry", "Historized", "Validated", "Velocity". Si les données ne correspondent pas aux valeurs attendues définies dans cette validation, les données sont rejetées.
Pour obtenir la liste complète des règles de propriété de validation prises en charge, voir Informations de référence sur l'extension de validationDTMI.
model.json
{
"@context":[
"dtmi:dtdl:context;3",
"dtmi:dtdl:extension:historization;1",
"dtmi:com:oracle:dtdl:extension:validation;1",
"dtmi:dtdl:extension:quantitativeTypes;1"
],
"@id":"dtmi:com:oracle:iot:poc:testmodel;1",
"@type":"Interface",
"contents":[
{
"@type":[ "Telemetry", "Historized", "Validated", "Velocity" ],
"displayName":"Speed",
"name":"speed",
"schema":"integer",
"unit":"milePerHour",
"minimum":0,
"maximum":100
}
]
}envelope.json
{
"referenceEndpoint": "telemetry/automotive/usa-standard-units",
"referencePayload": {
"dataFormat": "JSON",
"data": {
"speed": 65
}
}
}
routes.json listé ci-dessous contient 3 expressions qui transforment les kilomètres et normalise les données utiles en une unité de mesure, miles par heure :- Expression de condition qui évalue les données du point d'extrémité :
"condition" : "${endpoint(3) == \"metric-units\"}"La syntaxe
${ ... }indique une expression qui évalue la valeur du troisième paramètre de point d'extrémité ou élément de chemin dans un appel d'APIendpoint(3). La condition compare la valeur retournée àmetric-units. S'il est vrai, il applique ces règles. - Expression de mappage de données utiles :
"payloadMapping" : { "$.speed": "${(.velocity_kph / 1.609) | floor}"}La syntaxe
${ ... }indique une expression. Cette expression évalue et effectue un calcul arithmétique pour convertir la vitesse ou la vélocité des kilomètres à l'heure en milles à l'heure(.velocity_kph / 1.609). Cela divise le champvelocity_kphpar1.609, puis applique la fonction plancher, en arrondissant à l'entier le plus proche. Cette valeur provient de la conversion des kilomètres en miles qui est kilomètres = miles × 1,60934, "payloadMapping": {"$.speed": "$.speed"}Il s'agit d'une expression de mappage de valeur directe, passant par la valeur de vitesse telle quelle.
[
{
"description" : "Automotive data using metric units (kilometers) that's converted to miles, with a different external key in the digital twin instance",
"condition" : "${endpoint(3) == \"metric-units\"}",
"payloadMapping" : {
"$.speed": "${(.velocity_kph / 1.609) | floor}"
},
"referencePayload" : {
"dataFormat" : "JSON",
"data" : { "velocity_kph": 104 }
}
},
{
"description" : "Auto 1 and Auto 2 use USA standard units, shows speed as is.",
"condition" : "*",
"payloadMapping" : { "$.speed": "$.speed" }
}
]
Étape 1 : Créer un modèle de jumeau numérique
Utilisez cette commande d'interface de ligne de commande oci iot digital-twin-model create pour créer un modèle de jumeau numérique à l'aide du fichier model.json. Ce modèle numérique double standardise speed en miles par heure.
Cette commande enregistre le modèle de jumeau numérique avec cet URI DTMI dtmi:com:oracle:iot:poc:testmodel;1 tel que défini dans la mention model.json ci-dessus.
oci iot digital-twin-model create \
--iot-domain-id <iot-domain-ocid> \
--display-name "Test Digital Twin Model" \
--description "Model for testing automotive telemetry routing and unit normalization" \
--spec file://~/model.json
Étape 2 : Créer un adaptateur jumeau numérique avec une enveloppe et des itinéraires
Créez un adaptateur qui référence la spécification DTMI du modèle numérique jumelé et qui utilise l'enveloppe entrante et les itinéraires pour normaliser la télémétrie entrante.
oci iot digital-twin-adapter create \
--iot-domain-id <iot-domain-ocid> \
--display-name "automotive-speed-adapter" \
--description "Routes by units" \
--digital-twin-model-spec-uri "dtmi:com:oracle:iot:poc:testmodel;1" \
--inbound-envelope file://~/envelope.json \
--inbound-routes file://~/routes.json
referenceEndpoint dans envelope.json est telemetry/automotive/usa-standard-units. Le fichier routes.json :
- Achemine les demandes vers le troisième segment de chemin qui est égal à
metric-units, par exemple/telemetry/automotive/metric-units, puis convertitvelocity_kphenspeeden mi/h, et stocke le résultat. - Utilise une condition catch-all par défaut (
*) pour passer parspeedinchangé pour les automobiles qui utilisent des miles par heure.
Étape 3 : Créer deux instances de jumeau numérique
- Point d'extrémité pour mph :
https://device-host/telemetry/automotive/usa-standard-units - Point d'extrémité pour km/h :
https://device-host/telemetry/automotive/metric-units
Lorsque vous créez une instance de jumeau numérique avec authentification, vous pouvez utiliser une clé secrète de chambre forte ou un certificat mTLS pour vous authentifier. Pour des raisons de sécurité, il est recommandé de créer une clé secrète de chambre forte ou un certificat mTLS unique pour chaque instance de jumeau numérique. Toutes les ressources doivent se trouver dans la même région et la même location que toutes les autres ressources IoT connexes.
Si vous utilisez un certificat mTLS pour l'authentification, vous devez utiliser le nom commun du certificat comme clé externe : --external-key <common-name-from-certificate-details>, voir Scénario : Créer une instance de jumeau numérique qui utilise un certificat mTLS.
Un administrateur doit ajouter la politique pour créer des clés secrètes ou des certificats. Voir Étape 3 dans Préalables.
Instance double numérique pour les unités standard des États-Unis, miles par heure (mph), notez la clé externe :
american-auto-standard-unitsoci iot digital-twin-instance create \
--iot-domain-id <IoT-domain-ocid> \
--display-name "auto using miles per hour" \
--external-key american-auto-standard-units \
--digital-twin-adapter-id <same-digital-twin-adapter-ocid> \
--auth-id <secret-ocid-or-certificate-ocid>Instance jumeau numérique pour les unités métriques européennes, kilomètres par heure (kph), notez la clé externe : european-auto-metric-units
oci iot digital-twin-instance create \
--iot-domain-id <IoT-domain-ocid> \
--display-name "auto using kilometers per hour" \
--external-key european-auto-metric-units \
--digital-twin-adapter-id <same-digital-twin-adapter-ocid> \
--auth-id <secret-ocid-or-certificate-ocid>
Étape 4 : Envoyer un exemple de télémétrie pour valider le routage et le mappage
Pour envoyer de la télémétrie, vous avez besoin de la clé externe de la réponse de l'instance de jumeau numérique de l'étape 3, du mot de passe de l'appareil et du point d'extrémité de l'hôte de l'appareil.
Si l'instance de jumeau numérique utilise la clé secrète de la chambre forte pour l'authentification, vous devez l'utiliser comme valeur de clé secrète encodée de base 64 comme mot de passe de l'appareil.
- Clé externe : Remplacez
external-keyparexternal-keyà partir de l'instance de jumeau numérique avec laquelle vous voulez travailler. Pour éviter les problèmes de soumission, il est recommandé de ne pas utiliser de guillemets dans la valeur de clé externe. - Mot de passe de l'appareil : Remplacez le mot de passe de l'appareil par le contenu de clé secrète en texte brut ou par le certificat mTLS.
- Hôte de l'appareil : Remplacez
device-hostpar l'hôte de votre appareil à partir de votre domaine IoT. Pour obtenir l'URL du point d'extrémité de l'hôte de l'appareil pour le domaine IoT, voir Obtention des détails d'un domaine IoT.
-u "external-key:device-password-secret-contents-or-certificate"
Selon votre système d'exploitation ou votre application, certaines applications ou certains éditeurs de code peuvent ajouter des devis indésirables à vos valeurs, ce qui peut entraîner une erreur. Pour obtenir des exemples de soumissions, voir Dépannage.
curl -i -X POST \
-u "european-auto-metric-units:device-password-secret-or-certificate" \
-H "Content-Type: application/json" \
"https://device-host/telemetry/automotive/metric-units" \
-d '{ "velocity_kph": 0 }'curl -i -X POST \
-u "european-auto-metric-units:device-password-secret-or-certificate" \
-H "Content-Type: application/json" \
"https://device-host/telemetry/automotive/metric-units" \
-d '{ "velocity_kph": 110 }'
curl -i -X POST \
-u "american-auto-standard-units:device-password-secret-or-certificate" \
-H "Content-Type: application/json" \
"https://device-host/telemetry/automotive/usa-standard-units" \
-d '{ "speed": 0 }'
curl -i -X POST \
-u "american-auto-standard-units:device-password-vault-secret-base-64-or-certificate-OCID" \
-H "Content-Type: application/json" \
"https://device-host/telemetry/automotive/usa-standard-units" \
-d '{ "speed": 60 }'
Étape 5 : Vérifier le comportement de la normalisation
La condition de routage ${endpoint(3) == "metric-units"} évalue les données et applique le mappage de données utiles suivant au point d'extrémité de données d'unités de mesure :
"$.speed": "${(.velocity_kph / 1.609) | floor}"
Résultat prévu :
- Le mappage de l'adaptateur convertit les kilomètres par heure (kph) en miles par heure (mph), puis applique le plancher pour satisfaire un schéma entier :
speed_mph = floor(velocity_kph / 1.609) - Dans cet exemple,
velocity_kph = 0: speed_mph = floor(0 / 1.609) = floor(0) = 0 mphAprès plancher indique l'étape d'arrondissement qui force le résultat à un nombre entier, arrondi vers l'infini négatif. Ceci est requis lorsque votre modèle DTDL déclare la télémétrie de vitesse comme
schema: "integer"de sorte que la valeur est un entier, pas un float ou une chaîne. velocity_kph = 110→speed = floor(110 / 1.609) = 68mi/h- Les publications de données standard avec
speedpassent inchangées, par exemple les valeurs de cet exemple :0,60
Si la validation du modèle est activée minimum: 0, maximum: 100, les valeurs hors limites sont rejetées en fonction des règles de validation.
Utilise la conversion de type flexible :
- Pass-through (mph, schéma "integer") :
{"speed": "60"}et{"speed": 60.0}sont stockés comme60.{"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.
Meilleures pratiques
- Fichiers JSON de référence pour les spécifications et les adaptateurs de modèle jumeau numérique : Lorsque vous chargez un adaptateur à l'aide de l'interface de ligne de commande, vous pouvez utiliser des fichiers JSON pour spécifier le mappage de données. Dans les commandes de l'interface de ligne de commande, vous pouvez référencer des fichiers en tant que
file://~/name.jsonou fournir un chemin absolu ou relatif en fonction de votre environnement d'interpréteur de commandes. Selon votre système d'exploitation, vous pouvez avoir une syntaxe légèrement différente avec des guillemets, des barres obliques ou l'emplacement du fichier par défaut. Voir Gestion de l'entrée et de la sortie de l'interface de ligne de commande et Utilisation d'un fichier JSON pour une entrée complexe. - Les fichiers de configuration JSON (enveloppe, routes) utilisent des noms de champ d'API dans
camelCase(par exemple,referenceEndpoint). L'interface de ligne de commande OCI transmet ces fichiers sans modification au moyen des argumentsfile://. L'utilisation du JSON camelCase avec l'interface de ligne de commande est donc attendue et correcte. referenceEndpointdansenvelope.jsondoit refléter un point d'extrémité standard pour votre adaptateur.- La condition de routage générique (
*) est évaluée après des conditions spécifiques; commandez vos définitions de routage en conséquence. - Portée 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, 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.
Variation : Utilisation de schema="double" au lieu de floor
Cette variante montre comment le réglage du schéma de propriété de modèle à double affecte le mappage d'adaptateur et les valeurs enregistrées. Avec double, le valideur accepte toute valeur entière ou fractionnée numérique qui répond aux contraintes d'intervalle, sans arrondissement automatique. Vous pouvez choisir de conserver la précision fractionnelle (brut) ou de forcer les nombres entiers à l'aide de floor. Validation des deux réussites tant que les valeurs restent dans l'intervalle défini.
Ce que fait la validation schema=double
- Acceptation de type : Accepte les nombres JSON avec ou sans parties fractionnaires, par exemple : 60, 68.35. Les chaînes telles que
"68"ne sont pas valides. - Intervalle : Les valeurs minimale et maximale, par exemple,
0–100dans cet exemple, sont appliquées. - Aucun arrondissement automatique : La plate-forme IoT n'arrondit pas les valeurs. Vous contrôlez l'arrondissement dans le mappage d'adaptateur jumeau numérique ou en aval à l'aide d'APEX ou SQL, selon les systèmes configurés pour voir vos données.
Fichiers utilisés dans cette variante :
model_double.json— Modèle DTDL avecschema: "double".{ "@context": [ "dtmi:dtdl:context;3", "dtmi:dtdl:extension:historization;1", "dtmi:com:oracle:dtdl:extension:validation;1", "dtmi:dtdl:extension:quantitativeTypes;1" ], "@id": "dtmi:com:oracle:iot:poc:testmodeldouble;1", "@type": "Interface", "contents": [ { "@type": [ "Telemetry", "Historized", "Validated", "Velocity" ], "displayName": "Speed", "name": "speed", "schema": "double", "unit": "milePerHour", "minimum": 0, "maximum": 100 } ] }routes_double_raw.json— Le mappage conserve la précision fractionnelle :"$.speed": "${.velocity_kph / 1.609}".[ { "description": "Double model: European metric units to miles per hour (mph); preserving fractional precision (no floor).", "condition": "${endpoint(3) == \"metric-units\"}", "payloadMapping": { "$.speed": "${.velocity_kph / 1.609}" }, "referencePayload": { "dataFormat": "JSON", "data": { "velocity_kph": 110 } } }, { "description": "Double model: USA standard units passthrough.", "condition": "*", "payloadMapping": { "$.speed": "$.speed" } } ]routes_double_floor.json— Le mappage est forcé au nombre entier mph :"$.speed": "${(.velocity_kph / 1.609) | floor}"stocké en tant que double.[ { "description": "Double model: European metric units to miles per hour (mph); floor to whole number (stored as double).", "condition": "${endpoint(3) == \"metric-units\"}", "payloadMapping": { "$.speed": "${(.velocity_kph / 1.609) | floor}" }, "referencePayload": { "dataFormat": "JSON", "data": { "velocity_kph": 110 } } }, { "description": "Double model: USA standard units passthrough.", "condition": "*", "payloadMapping": { "$.speed": "$.speed" } } ]
Étape A : Créer un modèle jumeau numérique en utilisant double
oci iot digital-twin-model create \
--iot-domain-id iot-domain-ocid \
--display-name "TestModelSpeedDouble" \
--spec file://model_double.json
Étape B : Créer deux adaptateurs associés au modèle double
Utilisez des valeurs brutes pour préserver la précision fractionnelle :
oci iot digital-twin-adapter create \
--iot-domain-id iot-domain-ocid \
--display-name "auto-adapter-double-raw" \
--digital-twin-model-id double-model-ocid \
--inbound-envelope file://envelope.json \
--inbound-routes file://routes_double_raw.json
Floor utilise un nombre entier comme mph, c'est un double :
oci iot digital-twin-adapter create \
--iot-domain-id iot-domain-ocid \
--display-name "auto-adapter-double-floor" \
--digital-twin-model-id double-model-ocid \
--inbound-envelope file://envelope.json \
--inbound-routes file://routes_double_floor.json
Étape C : Créer des instances de jumeau numérique pour chaque adaptateur
oci iot digital-twin-instance create \
--iot-domain-id iot-domain-ocid \
--display-name "american-auto-raw" \
--external-key american-auto-raw \
--digital-twin-adapter-id adapter-double-raw-ocid \
--auth-id vault-secret-ocid
oci iot digital-twin-instance create \
--iot-domain-id iot-domain-ocid \
--display-name "european-auto-raw" \
--external-key european-auto-raw \
--digital-twin-adapter-id adapter-double-raw-ocid \
--auth-id vault-secret-ocid
oci iot digital-twin-instance create \
--iot-domain-id iot-domain-ocid \
--display-name "american-auto-dfloor" \
--external-key american-auto-dfloor \
--digital-twin-adapter-id adapter-double-floor-ocid \
--auth-id vault-secret-ocid
oci iot digital-twin-instance create \
--iot-domain-id iot-domain-ocid \
--display-name "european-auto-dfloor" \
--external-key european-auto-dfloor \
--digital-twin-adapter-id adapter-double-floor-ocid \
--auth-id vault-secret-ocid
Étape D : Post échantillon de télémétrie et comparer les résultats
-u "external-key:device-password" \- Si le jumeau numérique utilise une clé secrète de chambre forte pour l'authentification, utilisez
base64-secretcomme mot de passe de l'appareil. - Si l'instance de jumeau numérique utilise une certification mLTS, utilisez
certificate-ocidcomme mot de passe de l'appareil.
Valeurs brutes (double, no floor) :
curl -i -X POST \
-u "american-auto-raw:device-password" \
-H "Content-Type: application/json" \
"https://device-host/telemetry/automotive/usa-standard-units" \
-d '{ "speed": 60 }'
curl -i -X POST \
-u "european-auto-raw:device-password" \
-H "Content-Type: application/json" \
"https://device-host/telemetry/automotive/metric-units" \
-d '{ "velocity_kph": 110 }'
Résultat attendu : La deuxième publication produit environ 68.35… mph (fractionnel) et est acceptée car schema=double accepte les nombres fractionnaires dans l'intervalle.
Étage (double, avec plancher) :
curl -i -X POST \
-u "american-auto-dfloor:device-password" \
-H "Content-Type: application/json" \
"https://device-host/telemetry/automotive/usa-standard-units" \
-d '{ "speed": 60 }'
curl -i -X POST \
-u "european-auto-dfloor:device-password" \
-H "Content-Type: application/json" \
"https://device-host/telemetry/automotive/metric-units" \
-d '{ "velocity_kph": 110 }'
Résultat attendu : La deuxième publication produit 68 un nombre entier et est accepté. La valeur est stockée en tant que double, par exemple 68.0, même s'il s'agit d'un nombre entier.
Notes sur les soumissions de nom d'utilisateur et l'incidence en aval
- La clé externe est égale au nom d'utilisateur d'authentification : Si une instance de jumeau numérique est créée à l'aide de guillemets dans la valeur de la clé externe, par exemple
"\"american-auto-standard-units\"", le nom d'utilisateur d'authentification de base dans votre demandecurldoit inclure les guillemets, ou une non-concordance se produit et entraîne une erreur401 Unauthorized. Pour éviter les problèmes de soumission de devis, il est recommandé de ne pas utiliser de guillemets dans votre valeur de clé externe comme dans les exemples de ce scénario. - En aval dans APEX ou à l'aide de SQL : Avec
schema=double, les valeurs MP fractionnaires sont conservées. Si vous avez besoin de nombres entiers dans les rapports, appliquezFLOORetROUNDen SQL, par exempleSELECT FLOOR(speed) FROM …. Avecschema=integer, assurez-vous que le mappage émet des valeurs intégrales, par exemple, en utilisantfloorpour satisfaire la saisie de nombres entiers. - Prise en charge des expressions :
inbound-routeaccepte l'arithmétique etfloor. Les fonctions telles quetoIntegerounumberont été rejetées et ne sont pas prises en charge; utilisezfloorou adoptezschema: "double"pour une acceptation fractionnaire.