Convenciones de IoT Plug and Play

Los dispositivos de IoT Plug and Play deben seguir un conjunto de convenciones cuando intercambien mensajes con un centro de IoT. Los dispositivos de IoT Plug and Play usan el protocolo MQTT para comunicarse con IoT Hub. IoT Hub también admite el protocolo AMQP que está disponible en algunos SDK de dispositivo IoT.

Un dispositivo puede incluir módulos o implementarse en un módulo de IoT Edge hospedado por el tiempo de ejecución de IoT Edge.

Describe la telemetría, las propiedades y los comandos que implementa un dispositivo IoT Plug and Play con un modelo de lenguaje de definición de Digital Twins (DTDL). En este artículo se hace referencia a dos tipos de modelo:

  • Sin componentes: un modelo sin componentes. El modelo declara la telemetría, las propiedades y los comandos como elementos de nivel superior en la sección de contenido de la interfaz principal. En la herramienta de exploración Azure IoT, este modelo aparece como un único componente predeterminado.
  • Varios componentes: modelo compuesto por dos o más interfaces. Una interfaz principal, que aparece como componente predeterminado, con telemetría, propiedades y comandos. Una o más interfaces declaradas como componentes con telemetría, propiedades y comandos adicionales.

Para más información, consulte la Guía de modelado de IoT Plug and Play.

Identificación del modelo

Para anunciar el modelo que implementa, un dispositivo o módulo IoT Plug and Play incluye el identificador del modelo en el paquete de conexión MQTT agregando model-id al campo USERNAME.

Para identificar el modelo que implementa un dispositivo o módulo, un servicio puede obtener el identificador de modelo en:

  • El campo modelId del dispositivo gemelo.
  • El campo $metadata.$model del gemelo digital.
  • Una notificación de cambios de gemelo digital.

Telemetría

  • La telemetría enviada desde un dispositivo sin componentes no requiere metadatos adicionales. El sistema agrega la propiedad dt-dataschema.
  • La telemetría enviada desde un dispositivo con componentes debe agregar el nombre del componente al mensaje de telemetría.
  • Al usar MQTT, agregue la $.sub propiedad con el nombre del componente al tema de telemetría, el sistema agrega la dt-subject propiedad .
  • Al usar AMQP, agregue la dt-subject propiedad con el nombre del componente como una anotación de mensaje.

Nota:

La telemetría de los componentes requiere un mensaje por componente.

Para obtener más ejemplos de telemetría, consulte Telemetría de cargas.>

Propiedades de solo lectura

Un dispositivo establece una propiedad de solo lectura que, a continuación, informa a la aplicación back-end.

Propiedad de solo lectura sin componentes de ejemplo

Un dispositivo o módulo puede enviar cualquier JSON válido que siga las reglas de DTDL.

DTDL que define una propiedad en una interfaz:

{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:example: Thermostat;1",
  "@type": "Interface",
  "contents": [
    {
      "@type": "Property",
      "name": "temperature",
      "schema": "double"
    }
  ]
}

Ejemplo de carga de propiedad notificada:

"reported" :
{
  "temperature" : 21.3
}

Propiedad de solo lectura de varios componentes de ejemplo

El dispositivo o módulo debe agregar el marcador {"__t": "c"} para indicar que el elemento hace referencia a un componente.

DTDL que hace referencia a un componente:

{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:com:example:TemperatureController;1",
  "@type": "Interface",
  "displayName": "Temperature Controller",
  "contents": [
    {
      "@type" : "Component",
      "schema": "dtmi:com:example:Thermostat;1",
      "name": "thermostat1"
    }
  ]
}

DTDL que define el componente:

{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:com:example:Thermostat;1",
  "@type": "Interface",
  "contents": [
    {
      "@type": "Property",
      "name": "temperature",
      "schema": "double"
    }
  ]
}

Ejemplo de carga de propiedad notificada:

"reported": {
  "thermostat1": {
    "__t": "c",
    "temperature": 21.3
  }
}

Para obtener más ejemplos de propiedades de solo lectura, vea Propiedades de cargas>.

Propiedades editables

Una aplicación back-end establece una propiedad grabable que IoT Hub envía al dispositivo.

El dispositivo o módulo debe confirmar que recibió la propiedad mediante el envío de una propiedad notificada. La propiedad notificada debe incluir:

  • value: el valor real de la propiedad (normalmente el valor recibido, pero el dispositivo puede decidir informar de un valor diferente).
  • ac: un código de confirmación que usa un código de estado HTTP.
  • av: una versión de confirmación que hace referencia a la $version de la propiedad deseada. Puede encontrar este valor en la carga de JSON de la propiedad deseada.
  • ad : una descripción de confirmación opcional.

Respuestas de confirmación

Al notificar propiedades grabables, el dispositivo debe redactar el mensaje de confirmación, mediante el uso de los cuatro campos de la lista anterior, para indicar el estado real del dispositivo, como se describe en la tabla siguiente:

Status(ac) Version(av) Value(value) Description(av)
200 Versión deseada Valor deseado Valor de propiedad deseado y aceptado
202 Versión deseada Valor aceptado por el dispositivo Valor de propiedad deseado aceptado; actualización en curso (debe finalizar con 200)
203 0 Valor aceptado por el dispositivo Propiedad establecida desde el dispositivo, no refleja ningún elemento deseado
400 Versión deseada Valor usado por el dispositivo Valor de propiedad deseado, pero no aceptado
500 Versión deseada Valor usado por el dispositivo Excepción al aplicar la propiedad

Cuando se inicia un dispositivo, debe solicitar el dispositivo gemelo y comprobar si hay actualizaciones de propiedades que se puedan escribir. Si la versión de una propiedad grabable aumenta mientras el dispositivo estaba sin conexión, el dispositivo debe enviar una respuesta de propiedad notificada para confirmar que recibió la actualización.

Cuando un dispositivo se inicia por primera vez, puede enviar un valor inicial para una propiedad notificada si no recibe una propiedad inicial deseada del centro de IoT. En este caso, el dispositivo puede enviar el valor predeterminado con av a 0 y ac a 203. Por ejemplo:

"reported": {
  "targetTemperature": {
    "value": 20.0,
    "ac": 203,
    "av": 0,
    "ad": "initialize"
  }
}

Un dispositivo puede usar la propiedad notificada para proporcionar otra información al centro. Por ejemplo, el dispositivo puede responder con una serie de mensajes en curso, como:

"reported": {
  "targetTemperature": {
    "value": 35.0,
    "ac": 202,
    "av": 3,
    "ad": "In-progress - reporting current temperature"
  }
}

Cuando el dispositivo alcanza la temperatura de destino, envía el siguiente mensaje:

"reported": {
  "targetTemperature": {
    "value": 20.0,
    "ac": 200,
    "av": 4,
    "ad": "Reached target temperature"
  }
}

Un dispositivo podría informar de un error como:

"reported": {
  "targetTemperature": {
    "value": 120.0,
    "ac": 500,
    "av": 3,
    "ad": "Target temperature out of range. Valid range is 10 to 99."
  }
}

Tipo de objeto

Si una propiedad grabable se define como un objeto, el servicio debe enviar un objeto completo al dispositivo. El dispositivo debe confirmar la actualización mediante el envío de información suficiente al servicio para que este comprenda cómo ha actuado el dispositivo en la actualización. Esta respuesta podría incluir:

  • Todo el objeto.
  • Solo los campos que ha actualizado el dispositivo.
  • Un subconjunto de los campos.

En el caso de objetos grandes, considere la posibilidad de minimizar el tamaño del objeto que se incluye en la confirmación.

En el ejemplo siguiente se muestra una propiedad grabable definida como Object con cuatro campos:

DTDL:

{
  "@type": "Property",
  "name": "samplingRange",
  "schema": {
    "@type": "Object",
    "fields": [
      {
        "name": "startTime",
        "schema": "dateTime"
      },
      {
        "name": "lastTime",
        "schema": "dateTime"
      },
      {
        "name": "count",
        "schema": "integer"
      },
      {
        "name": "errorCount",
        "schema": "integer"
      }
    ]
  },
  "displayName": "Sampling range"
  "writable": true
}

Para actualizar esta propiedad grabable, envíe un objeto completo desde el servicio que sea similar al siguiente ejemplo:

{
  "samplingRange": {
    "startTime": "2021-08-17T12:53:00.000Z",
    "lastTime": "2021-08-17T14:54:00.000Z",
    "count": 100,
    "errorCount": 5
  }
}

El dispositivo responde con una confirmación similar al siguiente ejemplo:

{
  "samplingRange": {
    "ac": 200,
    "av": 5,
    "ad": "Weighing status updated",
    "value": {
      "startTime": "2021-08-17T12:53:00.000Z",
      "lastTime": "2021-08-17T14:54:00.000Z",
      "count": 100,
      "errorCount": 5
    }
  }
}

Propiedad editable sin componentes de ejemplo

Cuando un dispositivo recibe varias propiedades deseadas en una sola carga, puede enviar las respuestas de propiedad notificadas entre varias cargas o combinar las respuestas en una sola carga.

Un dispositivo o módulo puede enviar cualquier JSON válido que siga las reglas de DTDL.

DTDL:

{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:example: Thermostat;1",
  "@type": "Interface",
  "contents": [
    {
      "@type": "Property",
      "name": "targetTemperature",
      "schema": "double",
      "writable": true
    },
    {
      "@type": "Property",
      "name": "targetHumidity",
      "schema": "double",
      "writable": true
    }
  ]
}

Carga de propiedades deseadas de ejemplo:

"desired" :
{
  "targetTemperature" : 21.3,
  "targetHumidity" : 80,
  "$version" : 3
}

Carga de primera propiedad notificada de ejemplo:

"reported": {
  "targetTemperature": {
    "value": 21.3,
    "ac": 200,
    "av": 3,
    "ad": "complete"
  }
}

Carga de segunda propiedad notificada de ejemplo:

"reported": {
  "targetHumidity": {
    "value": 80,
    "ac": 200,
    "av": 3,
    "ad": "complete"
  }
}

Nota:

También puede optar por combinar estas dos cargas de propiedad notificadas en una sola carga.

Propiedad editable de varios componentes de ejemplo

El dispositivo o módulo debe agregar el marcador {"__t": "c"} para indicar que el elemento hace referencia a un componente.

El marcador solo se envía para las actualizaciones de las propiedades definidas en un componente. Las actualizaciones de las propiedades definidas en el componente predeterminado no incluyen el marcador; consulte Propiedad editable sin componentes de ejemplo.

Cuando un dispositivo recibe varias propiedades notificadas en una sola carga, puede enviar las respuestas de propiedad notificadas entre varias cargas o combinar las respuestas en una sola carga.

El dispositivo o módulo debe confirmar que recibió las propiedades mediante el envío de propiedades notificadas:

DTDL que hace referencia a un componente:

{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:com:example:TemperatureController;1",
  "@type": "Interface",
  "displayName": "Temperature Controller",
  "contents": [
    {
      "@type" : "Component",
      "schema": "dtmi:com:example:Thermostat;1",
      "name": "thermostat1"
    }
  ]
}

DTDL que define el componente:

{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:com:example:Thermostat;1",
  "@type": "Interface",
  "contents": [
    {
      "@type": "Property",
      "name": "targetTemperature",
      "schema": "double",
      "writable": true
    }
  ]
}

Carga de propiedades deseadas de ejemplo:

"desired": {
  "thermostat1": {
    "__t": "c",
    "targetTemperature": 21.3,
    "targetHumidity": 80,
    "$version" : 3
  }
}

Carga de primera propiedad notificada de ejemplo:

"reported": {
  "thermostat1": {
    "__t": "c",
    "targetTemperature": {
      "value": 23,
      "ac": 200,
      "av": 3,
      "ad": "complete"
    }
  }
}

Carga de segunda propiedad notificada de ejemplo:

"reported": {
  "thermostat1": {
    "__t": "c",
    "targetHumidity": {
      "value": 80,
      "ac": 200,
      "av": 3,
      "ad": "complete"
    }
  }
}

Nota:

También puede optar por combinar estas dos cargas de propiedad notificadas en una sola carga.

Para obtener más ejemplos de propiedades grabables>, vea Propiedades de cargas.

Comandos

Las interfaces sin componentes usan el nombre del comando sin prefijo.

En un dispositivo o módulo, las interfaces con varios componentes usan nombres de comando con el siguiente formato: componentName*commandName.

Para obtener más ejemplos de comandos, consulte Comandos de cargas>.

Sugerencia

IoT Central tiene sus propias convenciones para implementar comandos de ejecución prolongada y comandos sin conexión.

Pasos siguientes

Ahora que aprendió sobre las convenciones de IoT Plug and Play, estos son algunos recursos adicionales: