Guia de modelagem IoT Plug and Play

No núcleo do IoT Plug and Play, está um modelo de dispositivo que descreve os recursos de um dispositivo para um aplicativo habilitado para IoT Plug and Play. Este modelo está estruturado como um conjunto de interfaces que definem:

  • Propriedades que representam o estado somente leitura ou gravável de um dispositivo ou outra entidade. Por exemplo, um número de série do dispositivo pode ser uma propriedade somente leitura e uma temperatura alvo em um termostato pode ser uma propriedade gravável.
  • Campos de telemetria que definem os dados emitidos por um dispositivo, quer os dados sejam um fluxo regular de leituras do sensor, um erro ocasional ou uma mensagem informativa.
  • Comandos que descrevem uma função ou operação que pode ser feita em um dispositivo. Por exemplo, um comando pode reiniciar um gateway ou tirar uma foto usando uma câmera remota.

Para saber mais sobre como o IoT Plug and Play usa modelos de dispositivo, consulte Guia do desenvolvedor de dispositivos IoT Plug and Play e Guia do desenvolvedor do serviço IoT Plug and Play.

Para definir um modelo, use a DTDL (Digital Twins Definition Language). DTDL usa uma variante JSON chamada JSON-LD. O trecho a seguir mostra o modelo de um dispositivo termostato que:

  • Tem um ID de modelo exclusivo: dtmi:com:example:Thermostat;1.
  • Envia telemetria de temperatura.
  • Tem uma propriedade gravável para definir a temperatura alvo.
  • Tem uma propriedade somente leitura para relatar a temperatura máxima desde a última reinicialização.
  • Responde a um comando que solicita temperaturas máximas, mínimas e médias durante um período de tempo.
{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:com:example:Thermostat;1",
  "@type": "Interface",
  "displayName": "Thermostat",
  "description": "Reports current temperature and provides desired temperature control.",
  "contents": [
    {
      "@type": [
        "Telemetry",
        "Temperature"
      ],
      "name": "temperature",
      "displayName": "Temperature",
      "description": "Temperature in degrees Celsius.",
      "schema": "double",
      "unit": "degreeCelsius"
    },
    {
      "@type": [
        "Property",
        "Temperature"
      ],
      "name": "targetTemperature",
      "schema": "double",
      "displayName": "Target Temperature",
      "description": "Allows to remotely specify the desired target temperature.",
      "unit": "degreeCelsius",
      "writable": true
    },
    {
      "@type": [
        "Property",
        "Temperature"
      ],
      "name": "maxTempSinceLastReboot",
      "schema": "double",
      "unit": "degreeCelsius",
      "displayName": "Max temperature since last reboot.",
      "description": "Returns the max temperature since last device reboot."
    },
    {
      "@type": "Command",
      "name": "getMaxMinReport",
      "displayName": "Get Max-Min report.",
      "description": "This command returns the max, min and average temperature from the specified time to the current time.",
      "request": {
        "name": "since",
        "displayName": "Since",
        "description": "Period to return the max-min report.",
        "schema": "dateTime"
      },
      "response": {
        "name": "tempReport",
        "displayName": "Temperature Report",
        "schema": {
          "@type": "Object",
          "fields": [
            {
              "name": "maxTemp",
              "displayName": "Max temperature",
              "schema": "double"
            },
            {
              "name": "minTemp",
              "displayName": "Min temperature",
              "schema": "double"
            },
            {
              "name": "avgTemp",
              "displayName": "Average Temperature",
              "schema": "double"
            },
            {
              "name": "startTime",
              "displayName": "Start Time",
              "schema": "dateTime"
            },
            {
              "name": "endTime",
              "displayName": "End Time",
              "schema": "dateTime"
            }
          ]
        }
      }
    }
  ]
}

O modelo de termostato tem uma única interface. Exemplos posteriores neste artigo mostram modelos mais complexos que usam componentes e herança.

Este artigo descreve como criar e criar seus próprios modelos e aborda tópicos como tipos de dados, estrutura de modelo e ferramentas.

Para saber mais, consulte a especificação Digital Twins Definition Language .

Nota

Atualmente, o IoT Central suporta DTDL v2 com uma extensão do IoT Central.

Estrutura do modelo

Propriedades, telemetria e comandos são agrupados em interfaces. Esta seção descreve como você pode usar interfaces para descrever modelos simples e complexos usando componentes e herança.

IDs do modelo

Cada interface tem um identificador de modelo de gêmeo digital exclusivo (DTMI). Modelos complexos usam DTMIs para identificar componentes. Os aplicativos podem usar as DTMIs que os dispositivos enviam para localizar definições de modelo em um repositório.

Os DTMIs devem usar a seguinte convenção de nomenclatura:

  • O prefixo DTMI é dtmi:.
  • O sufixo DTMI é o número da versão do modelo, como ;2.
  • O corpo do DTMI é mapeado para a pasta e o arquivo no repositório de modelos onde o modelo está armazenado. O número da versão faz parte do nome do arquivo.

Por exemplo, o modelo identificado pela DTMI dtmi:com:Example:Thermostat;2 é armazenado no arquivo dtmi/com/example/thermostat-2.json .

O trecho a seguir mostra o contorno de uma definição de interface com sua DTMI exclusiva:

{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:com:example:Thermostat;2",
  "@type": "Interface",
  "displayName": "Thermostat",
  "description": "Reports current temperature and provides desired temperature control.",
  "contents": [
    ...
  ]
}

Sem componentes

Um modelo simples, como o termostato mostrado anteriormente, não usa componentes incorporados ou em cascata. Telemetria, propriedades e comandos são definidos no contents nó da interface.

O exemplo a seguir mostra parte de um modelo simples que não usa componentes:

{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:com:example:Thermostat;1",
  "@type": "Interface",
  "displayName": "Thermostat",
  "description": "Reports current temperature and provides desired temperature control.",
  "contents": [
    {
      "@type": [
        "Telemetry",
        "Temperature"
      ],
      "name": "temperature",
      "displayName": "Temperature",
      "description": "Temperature in degrees Celsius.",
      "schema": "double",
      "unit": "degreeCelsius"
    },
    {
      "@type": [
        "Property",
...

Ferramentas como o Azure IoT Explorer e o designer de modelo de dispositivo IoT Central rotulam uma interface autônoma, como o termostato, como um componente padrão.

A captura de tela a seguir mostra como o modelo é exibido na ferramenta Azure IoT Explorer:

Captura de ecrã que mostra o componente predefinido na ferramenta Azure IoT explorer.

A captura de tela a seguir mostra como o modelo é exibido como o componente padrão no designer de modelo de dispositivo do IoT Central. Selecione Exibir identidade para ver a DTMI do modelo:

Captura de tela mostrando o modelo de termostato na ferramenta de designer de modelo de dispositivo IoT Central.

O ID do modelo é armazenado em uma propriedade gêmea do dispositivo, como mostra a captura de tela a seguir:

Captura de ecrã da ferramenta Azure IoT Explorer que mostra o ID do modelo numa propriedade de gémeo digital.

Um modelo DTDL sem componentes é uma simplificação útil para um dispositivo ou um módulo IoT Edge com um único conjunto de telemetria, propriedades e comandos. Um modelo que não usa componentes facilita a migração de um dispositivo ou módulo existente para ser um dispositivo ou módulo IoT Plug and Play - você cria um modelo DTDL que descreve seu dispositivo ou módulo real sem a necessidade de definir nenhum componente.

Gorjeta

Um módulo pode ser um módulo de dispositivo ou um módulo IoT Edge.

Reutilizar

Há duas maneiras de reutilizar definições de interface.

  • Use vários componentes em um modelo para fazer referência a outras definições de interface.
  • Use herança para estender definições de interface existentes.

Vários componentes

Os componentes permitem que você construa uma interface de modelo como uma montagem de outras interfaces.

Por exemplo, a interface do termostato é definida como um modelo. Você pode incorporar essa interface como um ou mais componentes ao definir o modelo do controlador de temperatura. No exemplo a seguir, esses componentes são chamados thermostat1 e thermostat2.

Para um modelo DTDL com vários componentes, há duas ou mais seções de componentes. Cada seção definiu @type e Component se refere explicitamente a um esquema, conforme mostrado no trecho a seguir:

{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:com:example:TemperatureController;1",
  "@type": "Interface",
  "displayName": "Temperature Controller",
  "description": "Device with two thermostats and remote reboot.",
  "contents": [
    {
      "@type": [
        "Telemetry",
        "DataSize"
      ],
      "name": "workingSet",
      "displayName": "Working Set",
      "description": "Current working set of the device memory in KiB.",
      "schema": "double",
      "unit": "kibibyte"
    },
    {
      "@type": "Property",
      "name": "serialNumber",
      "displayName": "Serial Number",
      "description": "Serial number of the device.",
      "schema": "string"
    },
    {
      "@type": "Command",
      "name": "reboot",
      "displayName": "Reboot",
      "description": "Reboots the device after waiting the number of seconds specified.",
      "request": {
        "name": "delay",
        "displayName": "Delay",
        "description": "Number of seconds to wait before rebooting the device.",
        "schema": "integer"
      }
    },
    {
      "@type" : "Component",
      "schema": "dtmi:com:example:Thermostat;1",
      "name": "thermostat1",
      "displayName": "Thermostat One",
      "description": "Thermostat One of Two."
    },
    {
      "@type" : "Component",
      "schema": "dtmi:com:example:Thermostat;1",
      "name": "thermostat2",
      "displayName": "Thermostat Two",
      "description": "Thermostat Two of Two."
    },
    {
      "@type": "Component",
      "schema": "dtmi:azure:DeviceManagement:DeviceInformation;1",
      "name": "deviceInformation",
      "displayName": "Device Information interface",
      "description": "Optional interface with basic device hardware information."
    }
  ]
}

Este modelo tem três componentes definidos na seção de conteúdo - dois Thermostat componentes e um DeviceInformation componente. A seção de conteúdo também inclui definições de propriedade, telemetria e comando.

As capturas de tela a seguir mostram como esse modelo aparece no IoT Central. As definições de propriedade, telemetria e comando no controlador de temperatura aparecem no componente Padrão de nível superior. As definições de propriedade, telemetria e comando para cada termostato aparecem nas definições de componentes:

Captura de tela mostrando o modelo de dispositivo controlador de temperatura no IoT Central.

Captura de tela mostrando os componentes do termostato no modelo de dispositivo controlador de temperatura no IoT Central.

Para saber como escrever código de dispositivo que interage com componentes, consulte Guia do desenvolvedor de dispositivos IoT Plug and Play.

Para saber como escrever código de serviço que interage com componentes em um dispositivo, consulte Guia do desenvolvedor do serviço IoT Plug and Play.

Herança

A herança permite reutilizar recursos em interfaces base para estender os recursos de uma interface. Por exemplo, vários modelos de dispositivos podem compartilhar recursos comuns, como um número de série:

Diagrama que mostra um exemplo de herança em um modelo de dispositivo. Uma interface de termostato e uma interface de controlador de fluxo compartilham recursos de uma interface base.

O trecho a seguir mostra um modelo DTML que usa a extends palavra-chave para definir a relação de herança mostrada no diagrama anterior:

[
  {
    "@context": "dtmi:dtdl:context;2",
    "@id": "dtmi:com:example:Thermostat;1",
    "@type": "Interface",
    "contents": [
      {
        "@type": "Telemetry",
        "name": "temperature",
        "schema": "double",
        "unit": "degreeCelsius"
      },
      {
        "@type": "Property",
        "name": "targetTemperature",
        "schema": "double",
        "unit": "degreeCelsius",
        "writable": true
      }
    ],
    "extends": [
      "dtmi:com:example:baseDevice;1"
    ]
  },
  {
    "@context": "dtmi:dtdl:context;2",
    "@id": "dtmi:com:example:baseDevice;1",
    "@type": "Interface",
    "contents": [
      {
        "@type": "Property",
        "name": "SerialNumber",
        "schema": "double",
        "writable": false
      }
    ]
  }
]

A captura de tela a seguir mostra esse modelo no ambiente de modelo de dispositivo do IoT Central:

Captura de tela mostrando a herança da interface no IoT Central.

Quando você escreve código do lado do dispositivo ou do lado do serviço, seu código não precisa fazer nada de especial para lidar com interfaces herdadas. No exemplo mostrado nesta seção, o código do dispositivo informa o número de série como se fizesse parte da interface do termostato.

Sugestões

Você pode combinar componentes e herança ao criar um modelo. O diagrama a seguir mostra um thermostat modelo herdado de uma baseDevice interface. A baseDevice interface tem um componente, que herda de outra interface:

Diagrama mostrando um modelo que usa componentes e herança.

O trecho a seguir mostra um modelo DTML que usa as extends palavras-chave e component para definir a relação de herança e o uso do componente mostrado no diagrama anterior:

[
  {
    "@context": "dtmi:dtdl:context;2",
    "@id": "dtmi:com:example:Thermostat;1",
    "@type": "Interface",
    "contents": [
      {
        "@type": "Telemetry",
        "name": "temperature",
        "schema": "double",
        "unit": "degreeCelsius"
      },
      {
        "@type": "Property",
        "name": "targetTemperature",
        "schema": "double",
        "unit": "degreeCelsius",
        "writable": true
      }
    ],
    "extends": [
      "dtmi:com:example:baseDevice;1"
    ]
  },
  {
    "@context": "dtmi:dtdl:context;2",
    "@id": "dtmi:com:example:baseDevice;1",
    "@type": "Interface",
    "contents": [
      {
        "@type": "Property",
        "name": "SerialNumber",
        "schema": "double",
        "writable": false
      },
      {
        "@type" : "Component",
        "schema": "dtmi:com:example:baseComponent;1",
        "name": "baseComponent"
      }
    ]
  }
]

Tipos de dados

Use tipos de dados para definir parâmetros de telemetria, propriedades e comando. Os tipos de dados podem ser primitivos ou complexos. Tipos de dados complexos usam primitivos ou outros tipos complexos. A profundidade máxima para tipos complexos é de cinco níveis.

Tipos primitivos

A tabela a seguir mostra o conjunto de tipos primitivos que você pode usar:

Tipo primitivo Description
boolean Um valor booleano
date Uma data completa, conforme definido na secção 5.6 do RFC 3339
dateTime Uma data-hora, conforme definido no RFC 3339
double Um ponto flutuante IEEE de 8 bytes
duration Uma duração no formato ISO 8601
float Um ponto flutuante IEEE de 4 bytes
integer Um inteiro de 4 bytes assinado
long Um inteiro de 8 bytes assinado
string Uma string UTF8
time A tempo inteiro, conforme definido na secção 5.6 do RFC 3339

O trecho a seguir mostra um exemplo de definição de telemetria que usa o double tipo no schema campo:

{
  "@type": "Telemetry",
  "name": "temperature",
  "displayName": "Temperature",
  "schema": "double"
}

Tipos de dados complexos

Os tipos de dados complexos são de matriz, enumeração, mapa, objeto ou um dos tipos geoespaciais.

Matrizes

Uma matriz é um tipo de dados indexável onde todos os elementos são do mesmo tipo. O tipo de elemento pode ser um tipo primitivo ou complexo.

O trecho a seguir mostra um exemplo de definição de telemetria que usa o Array tipo no schema campo. Os elementos da matriz são booleanos:

{
  "@type": "Telemetry",
  "name": "ledState",
  "schema": {
    "@type": "Array",
    "elementSchema": "boolean"
  }
}

Enumerações

Uma enumeração descreve um tipo com um conjunto de rótulos nomeados que mapeiam para valores. Os valores podem ser inteiros ou strings, mas os rótulos são sempre strings.

O trecho a seguir mostra um exemplo de definição de telemetria que usa o Enum tipo no schema campo. Os valores na enumeração são inteiros:

{
  "@type": "Telemetry",
  "name": "state",
  "schema": {
    "@type": "Enum",
    "valueSchema": "integer",
    "enumValues": [
      {
        "name": "offline",
        "displayName": "Offline",
        "enumValue": 1
      },
      {
        "name": "online",
        "displayName": "Online",
        "enumValue": 2
      }
    ]
  }
}

Mapas

Um mapa é um tipo com pares chave-valor onde os valores têm todos o mesmo tipo. A chave em um mapa deve ser uma cadeia de caracteres. Os valores em um mapa podem ser de qualquer tipo, incluindo outro tipo complexo.

O trecho a seguir mostra uma definição de propriedade de exemplo que usa o Map tipo no schema campo. Os valores no mapa são strings:

{
  "@type": "Property",
  "name": "modules",
  "writable": true,
  "schema": {
    "@type": "Map",
    "mapKey": {
      "name": "moduleName",
      "schema": "string"
    },
    "mapValue": {
      "name": "moduleState",
      "schema": "string"
    }
  }
}

Objetos

Um tipo de objeto é composto de campos nomeados. Os tipos de campos em um mapa de objetos podem ser tipos primitivos ou complexos.

O trecho a seguir mostra um exemplo de definição de telemetria que usa o Object tipo no schema campo. Os campos no objeto são dateTime, duratione string tipos:

{
  "@type": "Telemetry",
  "name": "monitor",
  "schema": {
    "@type": "Object",
    "fields": [
      {
        "name": "start",
        "schema": "dateTime"
      },
      {
        "name": "interval",
        "schema": "duration"
      },
      {
        "name": "status",
        "schema": "string"
      }
    ]
  }
}

Tipos geoespaciais

DTDL fornece um conjunto de tipos geoespaciais, com base em GeoJSON, para modelar estruturas de dados geográficos: point, multiPoint, lineString, multiLineString, polygon, e multiPolygon. Esses tipos são estruturas aninhadas predefinidas de matrizes, objetos e enumerações.

O trecho a seguir mostra um exemplo de definição de telemetria que usa o point tipo no schema campo:

{
  "@type": "Telemetry",
  "name": "location",
  "schema": "point"
}

Como os tipos geoespaciais são baseados em matrizes, eles não podem ser usados atualmente em definições de propriedade.

Tipos semânticos

O tipo de dados de uma propriedade ou definição de telemetria especifica o formato dos dados que um dispositivo troca com um serviço. O tipo semântico fornece informações sobre telemetria e propriedades que um aplicativo pode usar para determinar como processar ou exibir um valor. Cada tipo semântico tem uma ou mais unidades associadas. Por exemplo, celsius e fahrenheit são unidades para o tipo semântico de temperatura. Os painéis e análises do IoT Central podem usar as informações de tipo semântico para determinar como plotar valores de telemetria ou propriedade e unidades de exibição. Para saber como você pode usar o analisador de modelo para ler os tipos semânticos, consulte Compreender o analisador de modelo de gêmeos digitais.

O trecho a seguir mostra um exemplo de definição de telemetria que inclui informações de tipo semântico. O tipo Temperature semântico @type é adicionado à matriz, e o unit valor, degreeCelsius é uma das unidades válidas para o tipo semântico:

{
  "@type": [
    "Telemetry",
    "Temperature"
  ],
  "name": "temperature",
  "schema": "double",
  "unit": "degreeCelsius"
}

Localização

Aplicativos, como o IoT Central, usam informações no modelo para criar dinamicamente uma interface do usuário em torno dos dados trocados com um dispositivo IoT Plug and Play. Por exemplo, os blocos em um painel podem exibir nomes e descrições para telemetria, propriedades e comandos.

Os campos opcionais description e displayName no modelo contêm cadeias de caracteres destinadas ao uso em uma interface do usuário. Esses campos podem conter cadeias de caracteres localizadas que um aplicativo pode usar para renderizar uma interface do usuário localizada.

O trecho a seguir mostra um exemplo de definição de telemetria de temperatura que inclui cadeias de caracteres localizadas:

{
  "@type": [
    "Telemetry",
    "Temperature"
  ],
  "description": {
    "en": "Temperature in degrees Celsius.",
    "it": "Temperatura in gradi Celsius."
  },
  "displayName": {
    "en": "Temperature",
    "it": "Temperatura"
  },
  "name": "temperature",
  "schema": "double",
  "unit": "degreeCelsius"
}

Adicionar cadeias de caracteres localizadas é opcional. O exemplo a seguir tem apenas um único idioma padrão:

{
  "@type": [
    "Telemetry",
    "Temperature"
  ],
  "description": "Temperature in degrees Celsius.",
  "displayName": "Temperature",
  "name": "temperature",
  "schema": "double",
  "unit": "degreeCelsius"
}

Ciclo de vida e ferramentas

Os quatro estágios do ciclo de vida de um modelo de dispositivo são autor, publicação, uso e versão:

Autor

Os modelos de dispositivo DTML são documentos JSON que você pode criar em um editor de texto. No entanto, no IoT Central, você pode usar o ambiente GUI do modelo de dispositivo para criar um modelo DTML. No IoT Central você pode:

  • Crie interfaces que definam propriedades, telemetria e comandos.
  • Use componentes para montar várias interfaces juntas.
  • Definir relações de herança entre interfaces.
  • Importe e exporte arquivos de modelo DTML.

Para saber mais, consulte Definir um novo tipo de dispositivo IoT em seu aplicativo do Azure IoT Central.

Há uma extensão de criação DTDL para o VS Code.

Para instalar a extensão DTDL para VS Code, vá para o editor DTDL para Visual Studio Code. Você também pode pesquisar DTDL na visualização Extensões no VS Code.

Depois de instalar a extensão, use-a para ajudá-lo a criar arquivos de modelo DTDL no VS Code:

  • A extensão fornece validação de sintaxe em arquivos de modelo DTDL, destacando erros conforme mostrado na captura de tela a seguir:

    Captura de tela que mostra a validação do modelo DTDL no VS Code.

  • Use o intellisense e o preenchimento automático ao editar modelos DTDL:

    Captura de tela que mostra o intellisense para modelos DTDL no VS Code.

  • Crie uma nova interface DTDL. O comando DTDL: Create Interface cria um arquivo JSON com uma nova interface. A interface inclui exemplos de definições de telemetria, propriedade e comando.

Utilizar

Aplicativos, como o IoT Central, usam modelos de dispositivo. No IoT Central, um modelo faz parte do modelo de dispositivo que descreve os recursos do dispositivo. O IoT Central usa o modelo de dispositivo para criar dinamicamente uma interface do usuário para o dispositivo, incluindo painéis e análises.

Nota

O IoT Central define algumas extensões para a linguagem DTDL. Para saber mais, consulte Extensão do IoT Central.

Uma solução personalizada pode usar o analisador de modelo de gêmeos digitais para entender os recursos de um dispositivo que implementa o modelo. Para saber mais, consulte Usar modelos IoT Plug and Play em uma solução IoT.

Versão

Para garantir que os dispositivos e as soluções do lado do servidor que usam modelos continuem a funcionar, os modelos publicados são imutáveis.

A DTMI inclui um número de versão que você pode usar para criar várias versões de um modelo. Dispositivos e soluções do lado do servidor podem usar a versão específica para a qual foram projetados.

O IoT Central implementa mais regras de controle de versão para modelos de dispositivos. Se você fizer a versão de um modelo de dispositivo e seu modelo no IoT Central, poderá migrar dispositivos de versões anteriores para versões posteriores. No entanto, os dispositivos migrados não podem usar novos recursos sem uma atualização de firmware. Para saber mais, consulte Editar um modelo de dispositivo.

Publicar

A partir de fevereiro de 2024, o programa Azure Certified Device foi desativado. Portanto, a Microsoft não está mais aceitando envios de modelos DTDL para orepositório de modelos plug and play do Azure IoT.

Se quiser configurar seu próprio repositório de modelos, você pode usar o repositório de ferramentas de modelos plug and play do Azure IoT. Este repositório inclui o código para a dmr-client ferramenta CLI que pode validar, importar e expandir modelos DTDL. Essa ferramenta também permite indexar repositórios de modelos que seguem as convenções do repositório de modelos de dispositivos.

Limites e restrições

A lista a seguir resume algumas das principais restrições e limites dos modelos:

  • Atualmente, a profundidade máxima para matrizes, mapas e objetos é de cinco níveis.
  • Não é possível usar matrizes em definições de propriedade.
  • Você pode estender interfaces para uma profundidade de 10 níveis.
  • Uma interface pode estender no máximo duas outras interfaces.
  • Um componente não pode conter outro componente.

Próximos passos

Agora que você aprendeu sobre modelagem de dispositivos, aqui estão mais alguns recursos: