Scénario : normalisation des unités de mesure à l'aide d'un adaptateur jumeau numérique
Ce scénario explique comment utiliser un modèle de jumeau numérique, un adaptateur de jumeau numérique avec des mappings d'enveloppe et de routage pour normaliser une télémétrie spécifique dans un schéma commun, et comment valider le flux en publiant des exemples de charge utile de périphérique.
Ce scénario montre comment publier des données de télémétrie automobile avec différentes unités de mesure miles par heure et kilomètres par heure à l'aide d'adresses différentes, 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, reportez-vous à Référence : Expressions JQ pour les adaptateurs Jumeaux numériques.
Un adaptateur de jumeau numérique achemine les demandes par adresse et mappe les données traitées vers un modèle unique. Par exemple, le modèle de mesure envoie la vitesse en kilomètres par heure (velocity_kph) tandis qu'une autre instance de jumeau numérique standard envoie des miles par heure (speed).
Tâches
- Comprendre les fichiers inclus dans ce scénario
- Créer un modèle de jumeau numérique
- Création d'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 normalisation
Avant de débuter
Assurez-vous que vous disposez des droits d'accès requis et que l'interface de ligne de commande OCI est configurée. Pour plus d'informations, reportez-vous à Prérequis, à Détails de stratégie pour la plate-forme Internet of Things (IoT) et à Utilisation d'un fichier JSON pour les entrées complexes.
Comprenez les fichiers dans 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 de jumeau numérique basé sur les spécifications DTDL v3 avec une propriété de télémétriespeeden miles par heure qui utilise une extension de validation qui applique des limites sur la plage de valeurs allant de 0 à 100.envelope.json: configuration d'enveloppe qui déclare une adresse de référence et un exemple de forme de charge utile.routes.json: conditions de routage et correspondances de charge utile qui convertissent les kilomètres par heure en kilomètres 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 de jumeau numérique, un adaptateur et des instances, ainsi que les commandescurlpour POSTer un exemple de télémétrie, puis l'exécuter en tant que script shellscript.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
curlrépertoriées dans les étapes ci-dessous et exécuter ce scénario en tant que script shell :script.sh
Cet exemple de fragment 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 les 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, elles sont rejetées.
Pour obtenir la liste complète des règles de propriété de validation prises en charge, reportez-vous à Référence d'extension de validation DTMI.
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 répertorié ci-dessous contient 3 expressions qui transforment les kilomètres et normalisent la charge utile des données en une unité de mesure, miles par heure :- Expression de condition qui évalue les données de l'adresse :
"condition" : "${endpoint(3) == \"metric-units\"}"La syntaxe
${ ... }indique une expression qui évalue la valeur du troisième paramètre d'adresse ou élément de chemin dans un appel d'APIendpoint(3). La condition compare la valeur renvoyée àmetric-units. Si la valeur est True, ces règles sont appliquées. - Expression de mapping de charge utile :
"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 vitesse de kilomètres à l'heure en miles à l'heure.(.velocity_kph / 1.609)divise le champvelocity_kphpar1.609, puis applique la fonction de plancher, en arrondissant à l'entier le plus proche. Cette valeur provient de la conversion de kilomètres en miles qui est kilomètres = miles × 1.60934, "payloadMapping": {"$.speed": "$.speed"}Il s'agit d'une expression de mise en correspondance 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 de jumeau numérique 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 jumeau numérique et qui utilise l'enveloppe entrante et les routages 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
La valeur 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 mph et planifie le résultat. - Utilise une condition générique par défaut (
*) pour transmettrespeedsans modification pour les automobiles qui utilisent des miles par heure.
Etape 3 : création de deux instances de jumeau numérique
- Adresse pour mph :
https://device-host/telemetry/automotive/usa-standard-units - Adresse pour kph :
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 coffre ou un certificat mTLS pour l'authentification. Pour des raisons de sécurité, il est recommandé de créer une clé secrète de coffre 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 dans la même location que toutes les autres ressources IoT associées.
Si vous utilisez un certificat mTLS pour vous authentifier, vous devez utiliser le nom commun du certificat comme clé externe : --external-key <common-name-from-certificate-details>. Reportez-vous à Scénario : création d'une instance de jumeau numérique qui utilise un certificat mTLS.
Un administrateur doit ajouter la stratégie de création de clés secrètes ou de certificats. Reportez-vous à l'Step 3 in Prerequisites.
Instance de jumeau numérique pour les unités standard américaines, 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 de jumeaux numériques 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>
Etape 4 : envoyer un exemple de télémétrie pour valider le routage et le mappage
Pour envoyer 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 de l'adresse de l'hôte de l'appareil.
Si l'instance de jumeau numérique utilise la clé secrète du coffre pour s'authentifier, vous devez l'utiliser comme valeur de clé secrète encodée en base 64 en tant que mot de passe de l'appareil.
- Clé externe : remplacez
external-keyparexternal-keyde l'instance de jumeau numérique avec laquelle vous voulez travailler. Pour éviter les problèmes de citation, il est recommandé de ne pas utiliser de guillemets dans la valeur de clé externe. - Mot de passe du périphérique : remplacez le mot de passe du périphérique par le contenu de clé secrète en texte brut ou le certificat MTLS.
- Hôte de périphérique : remplacez
device-hostpar l'hôte de périphérique de votre domaine IoT. Afin d'obtenir l'URL d'adresse d'hôte de périphérique pour le domaine IoT, reportez-vous à Obtention des détails d'un domaine IoT.
-u "external-key:device-password-secret-contents-or-certificate"
En fonction de votre système d'exploitation ou de votre application, certaines applications ou certains éditeurs de code peuvent ajouter des guillemets indésirables à vos valeurs, ce qui peut entraîner une erreur. Reportez-vous à la section Troubleshooting pour obtenir des exemples de devis.
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 }'
Etape 5 : vérification du comportement de normalisation
La condition de routage ${endpoint(3) == "metric-units"} évalue les données et applique la mise en correspondance de charge utile suivante à l'adresse de données des unités de mesure :
"$.speed": "${(.velocity_kph / 1.609) | floor}"
Résultat attendu :
- Le mapping 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'arrondi qui force le résultat à un nombre entier, arrondi vers le bas vers l'infini négatif. Cela 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, et non une virgule flottante ou une chaîne. velocity_kph = 110→speed = floor(110 / 1.609) = 68mph- Les publications de données standard avec
speedpassent sans modification. Par exemple, les valeurs de cet exemple :0,60
Si la validation de modèle est activée minimum: 0, maximum: 100, les valeurs hors plage sont rejetées conformément aux règles de validation.
Utilise la conversion de type modifiable :
- 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 la mise en correspondance est contrainte sur un entier (par exemple, avecfloor). - Route de mesure (kph → mph) :
{"velocity_kph": 110}→68;{"velocity_kph": "110"}→68car le mappingfloorémet un entier. Conservez des entrées arithmétiques numériques pour éviter les erreurs d'expression. Dans la mesure du possible, préférez110à"110". - L'arrondi reste explicite : la conversion temporaire n'arrondi pas automatiquement
68.35à68. Utilisezfloorpour le schéma d'entiers ou basculez le modèle surschema: "double"pour conserver les fractions.
Meilleures pratiques
- Fichiers JSON de référence pour les spécifications et les adaptateurs de modèle de jumeau numérique : lorsque vous téléchargez un adaptateur à l'aide de l'interface de ligne de commande, vous pouvez utiliser des fichiers JSON pour indiquer la mise en correspondance des données. Dans les commandes de l'interface de ligne de commande, vous pouvez référencer les fichiers en tant que
file://~/name.jsonou fournir un chemin absolu ou relatif en fonction de votre environnement shell. 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. Reportez-vous à Gestion des entrées et sorties de l'interface de ligne de commande et à Utilisation d'un fichier JSON pour les entrées complexes. - Les fichiers de configuration JSON (enveloppe, routages) utilisent des noms de champ d'API dans
camelCase(par exemple,referenceEndpoint). L'interface de ligne de commande OCI transmet ces fichiers sans modification via des argumentsfile://. L'utilisation du format JSON camelCase avec l'interface de ligne de commande est donc attendue et correcte. - La valeur
referenceEndpointdansenvelope.jsondoit refléter une adresse standard pour votre adaptateur. - La condition de routage avec caractères génériques (
*) est évaluée après des conditions spécifiques. Triez les définitions de routage en conséquence. - Portée de la conversion douce : les chaînes de type numérique et les doubles de nombre entier sont acceptées lorsqu'elles correspondent au type de modèle (par exemple, entier). Les aides de conversion de type telles que
number()ettoIntegerne sont pas prises en charge dans les expressions de routage. Utilisez l'arithmétique etfloorou adoptezschema: "double"pour préserver les fractions.
Variation : utilisation de schema="double" au lieu de floor
Cette variation montre comment la définition du schéma de propriété de modèle sur double affecte le mapping d'adaptateur et les valeurs enregistrées. Avec double, le valideur accepte toute valeur entière ou fractionnelle numérique qui respecte les contraintes de plage, sans arrondi automatique. Vous pouvez choisir de conserver une précision fractionnée (brute) ou de forcer des nombres entiers à l'aide de floor. Les deux réussissent la validation tant que les valeurs restent dans la plage définie.
Fonctionnement de la validation schema=double
- Acceptation du 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. - Plage : les valeurs minimale et maximale, par exemple, dans cet exemple,
0–100sont appliquées. - Aucune arrondi automatique : la plate-forme IoT n'arrondit pas les valeurs. Vous contrôlez l'arrondi dans le mapping de votre adaptateur jumeau numérique ou en aval à l'aide d'APEX ou de SQL en fonction des systèmes configurés pour visualiser 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 mapping conserve la précision des fractions :"$.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 mapping se termine par un nombre entier de mph :"$.speed": "${(.velocity_kph / 1.609) | floor}"est 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 le modèle de 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
Etape B : création de deux adaptateurs associés au modèle double
Utilisez des valeurs brutes pour préserver la précision des fractions :
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-à-dire 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
Etape C : création d'instances de jumeaux numériques 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-échantillonnage de télémétrie et comparaison des résultats
-u "external-key:device-password" \- Si le jumeau numérique utilise une clé secrète de coffre pour s'authentifier, utilisez
base64-secretcomme mot de passe d'appareil. - Si l'instance de jumeau numérique utilise une certification mLTS, utilisez
certificate-ocidcomme mot de passe d'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 : le second message produit environ 68.35… mph (fractionnaire) et est accepté car schema=double accepte les nombres fractionnaires compris dans la plage.
Etage (double, avec étage) :
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 : le second message génère un nombre entier pour 68 et est accepté. La valeur est stockée en tant que valeur double, par exemple 68.0, même s'il s'agit d'un nombre entier.
Remarques sur les devis de nom d'utilisateur et leur impact en aval
- La clé externe est égale au nom utilisateur d'authentification : si une instance de jumeau numérique est créée à l'aide de guillemets dans la valeur de clé externe, par exemple,
"\"american-auto-standard-units\"", le nom 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 citation, 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 mph fractionnaires sont conservées. Si vous avez besoin de nombres entiers dans les rapports, appliquezFLOORetROUNDdans SQL, par exemple,SELECT FLOOR(speed) FROM …. Avecschema=integer, assurez-vous que le mapping émet des valeurs entières, par exemple, en utilisantfloorpour satisfaire la saisie d'entiers. - Prise en charge de l'expression :
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 fractionnée.