Gemelo digital

DTDL explicado: el Digital Twin Definition Language y cómo mapearlo a MQTT

Una introducción práctica a DTDL, el Digital Twin Definition Language: cómo funcionan las interfaces, la telemetría, las propiedades, los comandos, los componentes y las relaciones, y cómo mapearlos a topics MQTT en un broker.

Diagrama de un modelo DTDL con una interfaz de telemetría, propiedades y comandos mapeados a topics MQTT para un gemelo digital
Pruébalo en tu propio broker MQTTConsigue un broker MQTT privado y gestionado con el plan Free y empieza con ejemplos de código listos para usar.
Pruébalo gratis Ejemplos de código Sin tarjeta

DTDL, el Digital Twin Definition Language, es una forma basada en JSON de describir de qué está hecho un gemelo digital: la telemetría que emite, las propiedades que guarda, los comandos que acepta y cómo se relaciona con otros gemelos. En este artículo aprenderás cómo se estructuran los modelos DTDL, leerás un ejemplo completo y verás cómo mapear ese modelo a topics MQTT para que los dispositivos y las aplicaciones del gemelo compartan un contrato único y claro.

Para la visión general de dónde encajan los modelos, consulta nuestra guía de tecnología de gemelo digital.

Qué es DTDL y por qué existe

Cuando diez equipos construyen gemelos por su cuenta, cada uno inventa su propia forma de decir "esta bomba tiene un caudal en litros por minuto y un comando de arranque". DTDL estandariza esa descripción. Es un lenguaje abierto publicado por Microsoft, basado en JSON-LD y usado por Azure Digital Twins e IoT Plug and Play, pero nada en el propio lenguaje te ata a una nube concreta. Un archivo DTDL es simplemente un documento que describe un tipo de activo; puedes usarlo para generar código, validar payloads, construir interfaces o documentar contratos de topics.

El lenguaje ha pasado por varias versiones; DTDL v3 es la actual, y la v2 todavía aparece mucho en proyectos existentes. La especificación oficial está en el repositorio de DTDL en GitHub.

Los bloques de un modelo DTDL

Todo en DTDL se define dentro de una Interface. Una interfaz tiene un identificador y una lista de contenidos, cada uno de los cuales es uno de estos tipos de elemento:

Elemento Qué describe Ejemplo
Telemetry Un flujo de mediciones, no almacenado como estado Temperatura cada segundo
Property Un valor de estado, opcionalmente escribible Versión de firmware, consigna
Command Una operación que se le puede pedir al gemelo Arrancar, parar, reiniciar contador
Component Reutilización de otra interfaz dentro de esta Una bomba que contiene una interfaz de motor
Relationship Un enlace con otro gemelo Bomba isPartOf estación

Cada modelo y cada elemento tienen un DTMI (Digital Twin Model Identifier), como dtmi:com:example:Pump;1. El número final es la versión. Cuando cambias un modelo de forma incompatible, incrementas la versión en lugar de editarlo en el sitio.

Telemetría frente a propiedad

Esta es la distinción en la que más se equivocan los equipos. La telemetría es un flujo de eventos: te importa cada muestra y la plataforma del gemelo no guarda ningún "valor actual". Las propiedades son estado: el gemelo siempre tiene un valor actual, y una propiedad escribible puede fijarse desde el lado de la nube (un valor deseado) mientras el dispositivo informa de su valor real.

Regla práctica: si un nuevo visor necesita verlo nada más cargar, es una propiedad; si solo importa como serie a lo largo del tiempo, es telemetría.

Un ejemplo completo de DTDL

Esta es una interfaz DTDL v3 para una bomba centrífuga:

{
  "@context": "dtmi:dtdl:context;3",
  "@id": "dtmi:com:example:Pump;1",
  "@type": "Interface",
  "displayName": "Centrifugal Pump",
  "contents": [
    {
      "@type": ["Telemetry", "VolumeFlowRate"],
      "name": "flow",
      "schema": "double",
      "unit": "litrePerSecond"
    },
    {
      "@type": ["Telemetry", "Pressure"],
      "name": "dischargePressure",
      "schema": "double",
      "unit": "bar"
    },
    {
      "@type": "Property",
      "name": "running",
      "schema": "boolean"
    },
    {
      "@type": "Property",
      "name": "speedSetpoint",
      "schema": "double",
      "writable": true
    },
    {
      "@type": "Property",
      "name": "firmwareVersion",
      "schema": "string"
    },
    {
      "@type": "Command",
      "name": "resetRunHours"
    },
    {
      "@type": "Relationship",
      "name": "isPartOf",
      "target": "dtmi:com:example:PumpingStation;1"
    }
  ]
}

Los tipos semánticos como VolumeFlowRate y las unidades como litrePerSecond proceden de la extensión de tipos cuantitativos de DTDL. Permiten que las herramientas muestren las unidades correctamente sin adivinar. Consulta la especificación para ver la lista exacta de tipos semánticos y unidades válidos en la versión que uses.

Mapear DTDL a topics MQTT

DTDL describe qué contiene un gemelo; no dice cómo viajan los datos. MQTT es un transporte natural, y un mapeo limpio convierte tu modelo DTDL en un contrato de topics. Una convención práctica:

Elemento DTDL Topic MQTT Retenido QoS
Telemetry flow <asset>/telemetry (JSON con todos los campos de telemetría) No 0
Property (solo lectura) <asset>/properties/reported Sí 1
Valor deseado de una propiedad escribible <asset>/properties/desired Sí 1
Command resetRunHours <asset>/commands/resetRunHours No 1
Respuesta al comando <asset>/commands/resetRunHours/response No 1
Relationship Se guarda en el modelo o en el registro, no viaja por la red n/a n/a

Siendo <asset> una ruta ISA-95 como acme/site1/water/station3/pump2, un visor puede suscribirse a acme/site1/water/# y saber, gracias al modelo, cómo interpretar cada mensaje.

¿Por qué combinar la telemetría en un mensaje por activo? Publicar un topic por cada campo de telemetría multiplica el número de mensajes sin aportar información, y la mayoría de los consumidores quieren todos los campos con la misma marca de tiempo. Las propiedades se benefician de los retained messages para que los visores del gemelo obtengan el estado actual al instante; el tutorial gemelo digital con retained messages MQTT lo muestra en la práctica.

Validar payloads contra un modelo DTDL

Una vez que tienes un modelo, úsalo. Una pequeña comprobación en Python puede rechazar la telemetría que no coincida con la interfaz antes de que contamine tu histórico:

import json
import paho.mqtt.client as mqtt

with open("pump.json", encoding="utf-8") as f:
    model = json.load(f)

TYPE_MAP = {"double": (int, float), "boolean": bool, "string": str, "integer": int}
telemetry = {
    c["name"]: c["schema"]
    for c in model["contents"]
    if "Telemetry" in (c["@type"] if isinstance(c["@type"], list) else [c["@type"]])
}

def on_connect(client, userdata, flags, reason_code, properties):
    client.subscribe("connectmq/demo/d41f/+/+/+/+/telemetry")

def on_message(client, userdata, msg):
    data = json.loads(msg.payload)
    for name, schema in telemetry.items():
        if name not in data:
            print(f"{msg.topic}: missing {name}")
        elif not isinstance(data[name], TYPE_MAP[schema]):
            print(f"{msg.topic}: {name} should be {schema}")

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="dtdl-validator-d41f")
client.on_connect = on_connect
client.on_message = on_message
client.connect("broker.connectmq.com", 1883)
client.loop_forever()

Pruébalo publicando un mensaje de ejemplo en el servidor MQTT público gratuito, reservado para pruebas y prototipos:

mosquitto_pub -h broker.connectmq.com -p 1883 -i dtdl-pub-d41f \
  -t "connectmq/demo/d41f/acme/site1/station3/pump2/telemetry" \
  -m '{"flow": 12.4, "dischargePressure": "4.1"}'

El validador señala que dischargePressure es una cadena en lugar de un double, el tipo de error que, de otro modo, aparece semanas después en forma de gráfico roto.

Checklist de modelado DTDL

  1. Una interfaz por tipo de activo, no por instancia.
  2. Telemetría para flujos, propiedades para estado, comandos para acciones.
  3. Usa componentes para partes reutilizables como motores o sensores.
  4. Incluye las unidades mediante tipos semánticos siempre que sea posible.
  5. Versiona los DTMI y nunca rompas una versión publicada.
  6. Documenta el mapeo a MQTT junto al modelo, en el mismo repositorio.
  7. Valida los payloads en la ingesta, no solo en la interfaz.

DTDL comparado con otros modelos de gemelo

DTDL no es la única opción. La Asset Administration Shell, del mundo Industria 4.0, se centra en submodelos estandarizados para activos industriales y es habitual en la fabricación europea; consulta Asset Administration Shell explicada. Eclipse Ditto usa sus propios "things" JSON con atributos y features. Muchos equipos usan también un JSON Schema simple por tipo de activo. Lo que más importa es tener un modelo explícito y un mapeo documentado al transporte, que es justo el papel que DTDL desempeña bien. Para ver cómo se sitúa la capa de modelo junto a la mensajería, el estado y la visualización, consulta arquitectura de gemelo digital.

Ejecuta tu gemelo basado en DTDL en ConnectMQ

DTDL define el contrato; sigues necesitando un transporte fiable. ConnectMQ es un broker MQTT gestionado compatible con MQTT 3.1.1 y 5.0, con retained messages para las propiedades, TLS en el 8883 para los dispositivos y WSS en el 8084 para los gemelos en el navegador, como un gemelo digital 3D de una planta o un edificio. La validación de modelos, la generación de código y los grafos de gemelos se ejecutan en tus propias herramientas, conectadas a ConnectMQ como clientes MQTT normales. Crea un broker con el plan Serverless gratuito en app.connectmq.com, sin tarjeta de crédito, y publica en minutos tu primera telemetría con forma DTDL.

Preguntas frecuentes

¿DTDL es solo para Azure?

No. DTDL es un lenguaje abierto basado en JSON-LD. Azure Digital Twins lo usa de forma nativa, pero puedes usar modelos DTDL con cualquier transporte, incluido MQTT en cualquier broker.

¿Qué diferencia hay entre una propiedad y la telemetría en DTDL?

Una propiedad es estado con un valor actual, opcionalmente escribible; la telemetría es un flujo de mediciones en el que importa cada muestra, pero no se guarda ningún valor actual.

¿Cómo represento los comandos DTDL sobre MQTT?

Publica el comando en un topic de comandos no retenido con QoS 1 y un correlation ID, y haz que el dispositivo publique el resultado en un topic de respuesta. Las propiedades response topic y correlation data de MQTT 5 lo soportan directamente.

¿Qué versión de DTDL debería usar?

Usa DTDL v3 para proyectos nuevos, salvo que una herramienta de la que dependas solo soporte la v2.

Artículos relacionados

Todos los artículos →

Tu broker MQTT privado, a unos pocos clics

Crea una cuenta, obtén las credenciales de tu broker y conecta tu primer dispositivo, sin servidores que instalar, parchear ni escalar.