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 .
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:
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:
O ID do modelo é armazenado em uma propriedade gêmea do dispositivo, como mostra a captura de tela a seguir:
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.
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:
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:
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:
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:
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
, duration
e 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 Digital Twins.
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 VS Code que suporta DTDL v2 e DTDL v3.
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:
Use o intellisense e o preenchimento automático ao editar modelos DTDL:
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 Digital Twins 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 Dispositivo Certificado do Azure será desativado. Portanto, a Microsoft não está mais aceitando envios de modelos DTDL para o repositó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.
Entenda o analisador de modelo Digital Twins
A DTDL (Digital Twins Definition Language) é descrita na especificação DTDL. Os usuários podem usar o pacote NuGet do Digital Twins Model Parser para validar e consultar um modelo DTDL v2 ou v3. O modelo DTDL pode ser definido em vários arquivos.
Instalar o analisador de modelo DTDL
O analisador está disponível em NuGet.org com o ID: DTDLParser. Para instalar o analisador, use qualquer gerenciador de pacotes NuGet compatível, como o do Visual Studio ou da dotnet
CLI.
dotnet add package DTDLParser
Nota
No momento da escrita, a versão do analisador é 1.0.52
.
Use o analisador para validar e inspecionar um modelo
O DTDLParser é uma biblioteca que você pode usar para:
- Determine se um ou mais modelos são válidos de acordo com as especificações de idioma v2 ou v3.
- Identificar erros de modelagem específicos.
- Inspecione o conteúdo do modelo.
Um modelo pode ser composto por uma ou mais interfaces descritas em arquivos JSON. Você pode usar o analisador para carregar todos os arquivos que definem um modelo e, em seguida, validar todos os arquivos como um todo, incluindo quaisquer referências entre os arquivos.
O repositório DTDLParser para .NET inclui os seguintes exemplos que ilustram o uso do analisador:
- DTDLParserResolveSample mostra como analisar uma interface com referências externas, resolver as dependências usando o
Azure.IoT.ModelsRepository
cliente. - DTDLParserJSInteropSample mostra como usar o DTDL Parser do JavaScript em execução no navegador, usando o .NET JSInterop.
O repositório DTDLParser para .NET também inclui uma coleção de tutoriais que mostram como usar o analisador para validar e inspecionar modelos.
A API do analisador de modelo permite que muitos cenários automatizem ou validem tarefas que dependem de modelos DTDL. Por exemplo, você pode criar dinamicamente uma interface do usuário a partir das informações no modelo.
Próximos passos
Agora que você aprendeu sobre modelagem de dispositivos, aqui estão mais alguns recursos: