Escenario: Normalización de unidades de medida mediante un adaptador gemelo digital
En este escenario se explica cómo utilizar un modelo de gemelo digital, un adaptador de gemelo digital con asignaciones de sobre y ruta para normalizar la telemetría específica en un esquema común y cómo validar el flujo mediante la publicación de cargas útiles de dispositivos de muestra.
Este escenario demuestra cómo publicar datos de telemetría automotriz con diferentes unidades de medida de millas por hora y kilómetros por hora utilizando diferentes puntos finales, dos instancias gemelas digitales y dos claves externas diferentes. Para obtener más información sobre los patrones JQ a los que se hace referencia en este escenario, consulte Referencia: Expresiones JQ para adaptadores gemelos digitales.
Un adaptador gemelo digital ruta las solicitudes por punto final y asigna cargas útiles a un único modelo. Por ejemplo, el modelo de métrica envía la velocidad en kilómetros por hora (velocity_kph), mientras que otra instancia gemela digital estándar envía millas por hora (speed).
Tareas
- Describir los archivos incluidos en este escenario
- Creación de un modelo gemelo digital
- Cree un adaptador gemelo digital con sobre y rutas
- Creación de dos instancias gemelas digitales
- Enviar telemetría de ejemplo para validar el enrutamiento y la asignación
- Verificar el comportamiento de normalización
Antes de empezar
Asegúrese de que tiene los permisos necesarios y de que la CLI de OCI está configurada. Para obtener más información, consulte Requisitos, Detalles de política para la plataforma Internet of Things (IoT) y Uso de un archivo JSON para una entrada compleja.
Comprender los archivos de este escenario:
Los fragmentos de código que puede utilizar en su modelo gemelo digital al que se hace referencia en los siguientes pasos:
model.json: modelo gemelo digital basado en especificaciones de DTDL v3 con una propiedad de telemetríaspeeden millas por hora que utiliza una extensión de validación que aplica límites en el rango de valores de 0 a 100.envelope.json: configuración de sobre que declara un punto final de referencia y una unidad de carga útil de ejemplo.routes.json: condiciones de ruta y asignaciones de carga útil que convierten kilómetros por hora en millas por hora.script.sh: en este ejemplo, puede guardar todos los comandos de la CLI de OCI que se muestran a continuación para crear un modelo de gemelo digital, un adaptador y unas instancias, además de los comandoscurlen la telemetría de ejemplo POST y, a continuación, ejecutarlo como un script de shellscript.sh.Para completar los pasos de este escenario, puede crear y guardar la CLI de OCI y los comandos
curlque se muestran en los pasos siguientes y ejecutar este escenario como un script de shell:script.sh
Este fragmento de código model.json de modelo gemelo digital de ejemplo utiliza una extensión personalizada dtmi:com:oracle:dtdl:extension:validation;1 que aplica reglas de validación al esquema JSON para los elementos "Telemetry", "Historized", "Validated", "Velocity". Si los datos no coinciden con los valores esperados definidos en esta validación, los datos se rechazan.
Para obtener una lista completa de las reglas de propiedad de validación admitidas, consulte DTMI Validation Extension Reference (Referencia de extensión de validación deDTMI).
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 que se muestra a continuación contiene 3 expresiones que transforman los kilómetros y normalizan la carga útil de datos en una unidad de medida, millas por hora:- Expresión de condición que evalúa los datos del punto final:
"condition" : "${endpoint(3) == \"metric-units\"}"La sintaxis
${ ... }indica una expresión que evalúa el valor del parámetro de tercer punto final o el elemento de ruta de acceso en una llamada de APIendpoint(3). La condición compara el valor devuelto conmetric-units. Si es verdadero, aplica estas reglas. - Expresión de asignación de carga útil:
"payloadMapping" : { "$.speed": "${(.velocity_kph / 1.609) | floor}"}La sintaxis
${ ... }indica una expresión, esta expresión evalúa y realiza un cálculo aritmético para convertir la velocidad de kilómetros por hora a millas por hora(.velocity_kph / 1.609); esto divide el campovelocity_kphpor1.609y, a continuación, aplica la función de piso, redondeando hacia abajo al entero más cercano. Este valor proviene de la conversión de kilómetros a millas que es kilómetros = millas × 1.60934, "payloadMapping": {"$.speed": "$.speed"}Se trata de una expresión de asignación de valores directos, que pasa por el valor de velocidad tal cual.
[
{
"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" }
}
]
Paso 1: Crear un modelo gemelo digital
Utilice este comando de la CLI oci iot digital-twin-model create para crear un modelo gemelo digital mediante el archivo model.json. Este modelo gemelo digital estandariza speed en millas por hora.
Este comando registra el modelo de gemelo digital con este URI de DTMI dtmi:com:oracle:iot:poc:testmodel;1 como se define en la mención model.json anterior.
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
Paso 2: Crear un adaptador gemelo digital con un sobre y rutas
Cree un adaptador que haga referencia a la especificación de modelo de gemelo digital DTMI y que utilice el sobre entrante y las rutas para normalizar la telemetría 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 en envelope.json es telemetry/automotive/usa-standard-units. El archivo routes.json:
- Enruta las solicitudes al tercer segmento de ruta que es igual a
metric-units, por ejemplo,/telemetry/automotive/metric-unitsy, a continuación, conviertevelocity_kphaspeeden mph y planta el resultado. - Utiliza una condición catch-all por defecto (
*) para pasar a través despeedsin cambios para los automóviles que usan millas por hora.
Paso 3: Crear dos instancias gemelas digitales
- Punto final para mph:
https://device-host/telemetry/automotive/usa-standard-units - Punto final para kph:
https://device-host/telemetry/automotive/metric-units
Al crear una instancia de gemelo digital con autenticación, puede utilizar un secreto de almacén o un certificado mTLS para autenticarse. Por motivos de seguridad, se recomienda crear un secreto de almacén único o un certificado mTLS para cada instancia de gemelo digital. Todos los recursos deben estar en la misma región y arrendamiento que cualquier otro recurso IoT relacionado.
Si utiliza un certificado mTLS para autenticarse, debe utilizar el nombre común del certificado como clave externa: --external-key <common-name-from-certificate-details>. Consulte Escenario: Crear una instancia de gemelo digital que utilice un certificado mTLS.
Un administrador debe agregar la política para crear secretos o certificados. Consulte el Step 3 en Prerequisites.
Instancia gemela digital para unidades estándar de EE. UU., millas por hora (mph), observe la clave externa:
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>Instancia gemela digital para las unidades métricas europeas, kilómetros por hora (kph), observe la clave externa: 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>
Paso 4: Enviar telemetría de ejemplo para validar el enrutamiento y la asignación
Para enviar la telemetría, necesita la clave externa de la respuesta de la instancia de gemelo digital del paso 3, la contraseña del dispositivo y el punto final del host del dispositivo.
Si la instancia de gemelo digital utiliza el secreto de almacén para autenticarse, debe utilizar como valor secreto codificado base 64 como contraseña del dispositivo.
- Clave externa: sustituya
external-keyporexternal-keyde la instancia de gemelo digital con la que desea trabajar. Para evitar problemas de ofertas, se recomienda no utilizar comillas en el valor de clave externa. - Contraseña del dispositivo: sustituya la contraseña del dispositivo por el contenido del secreto de texto sin formato o el certificado mTLS.
- Host de dispositivo: sustituya
device-hostpor el host de dispositivo del dominio IoT. Para obtener la URL de punto final de host del dispositivo para el dominio IoT, consulte Obtención de detalles de un dominio IoT.
-u "external-key:device-password-secret-contents-or-certificate"
Según el sistema operativo o la aplicación, algunas aplicaciones o editores de código pueden agregar comillas no deseadas a los valores, lo que puede provocar un error. Consulte Solución de problemas para obtener ejemplos de comillas.
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 }'
Paso 5: Verificar el comportamiento de normalización
La condición de ruta ${endpoint(3) == "metric-units"} evalúa los datos y aplica la siguiente asignación de carga útil al punto final de datos de unidades de métrica:
"$.speed": "${(.velocity_kph / 1.609) | floor}"
Resultado esperado:
- La asignación del adaptador convierte kilómetros por hora (kph) a millas por hora (mph) y, a continuación, aplica suelo para satisfacer un esquema entero:
speed_mph = floor(velocity_kph / 1.609) - En este ejemplo,
velocity_kph = 0: speed_mph = floor(0 / 1.609) = floor(0) = 0 mphDespués del piso indica el paso de redondeo que obliga al resultado a un número entero, redondeando hacia abajo hacia el infinito negativo. Esto es necesario cuando el modelo DTDL declara la telemetría de velocidad como
schema: "integer", de modo que el valor es un entero, no un flotante o una cadena. velocity_kph = 110→speed = floor(110 / 1.609) = 68mph- Las publicaciones de datos estándar con
speedse transfieren sin cambios, por ejemplo, los valores de este ejemplo:0,60
Si la validación del modelo está activada minimum: 0, maximum: 100, los valores fuera de rango se rechazan según las reglas de validación.
Utiliza la conversión de tipo flexible:
- Transferencia (mph, esquema "integer"):
{"speed": "60"}y{"speed": 60.0}se almacenan como60.{"speed": "60.2"}se rechaza a menos que la asignación se asocie a un entero (por ejemplo, confloor). - Ruta métrica (kph → mph):
{"velocity_kph": 110}→68;{"velocity_kph": "110"}→68porque la asignaciónflooremite un número entero. Mantenga las entradas aritméticas numéricas para evitar errores de expresión; prefiera110en lugar de"110"cuando sea posible. - La redondeo sigue siendo explícita: la conversión flexible no redondea automáticamente
68.35a68. Utilicefloorpara el esquema entero o cambie el modelo aschema: "double"para conservar las fracciones.
Mejores prácticas
- Archivos JSON de referencia para adaptadores y especificaciones de modelo gemelo digital: al cargar un adaptador mediante la CLI, puede utilizar archivos JSON para especificar la asignación de datos. En los comandos de la CLI, puede hacer referencia a los archivos como
file://~/name.jsono proporcionar una ruta de acceso absoluta o relativa según el entorno de shell. Según el sistema operativo, puede que tenga una sintaxis ligeramente diferente con comillas, barras diagonales o la ubicación del archivo de forma predeterminada. Consulte Gestión de entrada y salida de la CLI y Uso de un archivo JSON para entrada compleja. - Los archivos de configuración JSON (sobre, rutas) utilizan nombres de campo de API en
camelCase(por ejemplo,referenceEndpoint). La CLI de OCI transfiere estos archivos a través de argumentosfile://sin cambios, por lo que se espera y se corrige el uso de JSON camelCase con CLI. referenceEndpointenenvelope.jsondebe reflejar un punto final típico para el adaptador.- La condición de ruta comodín (
*) se evalúa después de condiciones específicas; ordene las definiciones de ruta según corresponda. - Ámbito de conversión flexible: las cadenas de tipo numérico y los dobles de números enteros se aceptan cuando coinciden con el tipo de modelo (por ejemplo, entero). Los ayudantes de fundición como
number()ytoIntegersiguen sin estar soportados en las expresiones de ruta; confíen en la aritmética yfloor, o adoptenschema: "double"para conservar fracciones.
Variación: uso de schema="double" en lugar de floor
Esta variación muestra cómo la definición del esquema de propiedad de modelo en double afecta a la asignación del adaptador y a los valores registrados. Con double, el validador acepta cualquier valor numérico integral o fraccional que cumpla con las restricciones de rango, sin redondeo automático. Puede elegir conservar la precisión fraccional (cruda) o obligar a los números enteros mediante floor. Ambas pasan la validación siempre que los valores permanezcan dentro del rango definido.
Qué hace la validación schema=double
- Aceptación de tipo: acepta números JSON con o sin partes fraccionadas, por ejemplo: 60, 68.35. Las cadenas como
"68"siguen siendo no válidas. - Rango: mínimo y máximo, por ejemplo, en este ejemplo, se aplican
0–100. - Sin redondeo automático: la plataforma IoT no redondea los valores; puede controlar el redondeo en la asignación o descendente del adaptador de gemelos digitales mediante APEX o SQL en función de los sistemas configurados para ver los datos.
Archivos utilizados en esta variación:
model_double.json: modelo DTDL conschema: "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— La asignación conserva la precisión fraccional:"$.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: la asignación de coerces a mph de número entero:"$.speed": "${(.velocity_kph / 1.609) | floor}"se almacena como un doble.[ { "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" } } ]
Paso A: Crear el modelo gemelo digital con doble
oci iot digital-twin-model create \
--iot-domain-id iot-domain-ocid \
--display-name "TestModelSpeedDouble" \
--spec file://model_double.json
Paso B: Crear dos adaptadores asociados al modelo doble
Utilice valores raw para conservar la precisión fraccionada:
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 utiliza un número entero como mph, que es un doble:
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
Paso C: Crear dos instancias digitales para cada adaptador
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
Paso D: Postear la telemetría de la muestra y comparar los resultados
-u "external-key:device-password" \- Si el gemelo digital utiliza el secreto de almacén para autenticarse, utilice
base64-secretcomo contraseña del dispositivo. - Si la instancia de gemelo digital utiliza una certificación mLTS, utilice
certificate-ocidcomo contraseña del dispositivo.
Valores raw (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 }'
Resultado esperado: la segunda publicación produce aproximadamente 68.35… mph (fraccional) y aceptado porque schema=double acepta números fraccionarios dentro del rango.
Piso (doble, con suelo):
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 }'
Resultado esperado: la segunda publicación produce 68 en un número entero y es aceptado. El valor se almacena como un doble, por ejemplo, 68.0, aunque sea un número entero.
Notas sobre las comillas del nombre de usuario y el impacto descendente
- La clave externa es igual al nombre de usuario de autenticación: si se crea una instancia de gemelo digital mediante comillas en el valor de clave externa, por ejemplo,
"\"american-auto-standard-units\"", el nombre de usuario de autenticación básica en la solicitudcurldebe incluir las comillas, o si se produce una discrepancia y se produce un error401 Unauthorized. Para evitar problemas de ofertas, se recomienda no utilizar comillas en el valor de clave externa como en los ejemplos de este escenario. - Descendente en APEX o mediante SQL: con
schema=double, se conservan los valores de mph fraccionarios. Si necesita números enteros en los informes, apliqueFLOORyROUNDen SQL, por ejemplo,SELECT FLOOR(speed) FROM …. Conschema=integer, asegúrese de que la asignación emita valores integrales, por ejemplo, mediantefloorpara cumplir con la escritura de enteros. - Soporte de expresión:
inbound-routeacepta aritmética yfloor. Las funciones comotoIntegeronumberse han rechazado y no están soportadas; utiliceflooro adopteschema: "double"para la aceptación fraccionada.