Руководство моделирования IoT Plug and Play

В основе IoT Plug and Play лежит модель устройства, которая описывает возможности устройства в приложении с поддержкой IoT Plug and Play. Эта модель структурирована как набор интерфейсов, которые определяют следующее.

  • Свойства, которые отражают характеристики состояния устройства или другой сущности, доступные только для чтения или только для записи. Например, серийный номер устройства может быть свойством только для чтения, а требуемая температура для термостата — свойством только для записи.
  • Данные телеметрии, поля, которые отправляются устройством, например поток показаний датчика, сообщения об ошибках или информационные сообщения.
  • Команды описывают функции или операции, которые можно выполнить на устройстве. Например, можно определить команду для перезапуска шлюза или создания снимка дистанционно управляемой камерой.

Дополнительные сведения о том, как IoT Plug and Play использует модели устройств, см. в Руководстве для разработчика устройств IoT Plug and Play и Руководстве для разработчика служб IoT Plug and Play.

Для определения модели используется язык определения цифровых двойников (DTDL). DTDL использует вариант JSON, именуемый JSON-LD. В следующем фрагменте кода показана модель устройства термостата, которая...

  • Имеет уникальный идентификатор модели: dtmi:com:example:Thermostat;1.
  • Отправляет данные телеметрии о температуре.
  • Имеет свойство, доступное для записи, для задания целевой температуры.
  • Имеет свойство, доступное только для чтения, чтобы сообщать о максимальной температуре с момента последней перезагрузки.
  • Реагирует на команду, которая запрашивает максимальную, минимальную и среднюю температуры за период времени.
{
  "@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"
            }
          ]
        }
      }
    }
  ]
}

Модель термостата имеет единый интерфейс. В последующих примерах в этой статье демонстрируются более сложные модели, использующие компоненты и наследование.

В этой статье описывается разработка и создание собственных моделей, а также рассматриваются такие темы, как типы данных, структура модели и средства.

Дополнительные сведения см. в спецификации языка определения Digital Twins.

Примечание.

IoT Central в настоящее время поддерживает DTDL версии 2 с расширением IoT Central.

Структура модели

Свойства, данные телеметрии и команды группируются в интерфейсы. В этом разделе описывается использование интерфейсов для описания простых и сложных моделей с помощью компонентов и наследования.

Идентификаторы моделей

Каждый интерфейс имеет уникальный идентификатор модели цифрового двойника (DTMI). В сложных моделях DTMI используется для обнаружения компонентов. Приложения могут использовать DTMI, которые устройства отправляют для определения местоположения определений модели в репозитории.

DTMIs должен использовать следующее соглашение об именовании:

  • Префикс DTMI — dtmi:.
  • Суффикс DTMI — это номер версии для модели, например ;2.
  • Текст DTMI сопоставляется с папкой и файлом в репозитории модели, в котором хранится модель. Номер версии является частью имени файла.

Например, модель, определяемая параметром DTMI, dtmi:com:Example:Thermostat;2, хранится в файле dtmi/com/example/thermostat-2.json.

В следующем фрагменте кода показана структура определения интерфейса с уникальным DTMI.

{
  "@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": [
    ...
  ]
}

Без компонентов

Простая модель, например модель термостата, показанная ранее, не использует внедренные или каскадные компоненты. Данные телеметрии, свойств и команд определяются в узле contents интерфейса.

В следующем примере показана часть простой модели, которая не использует компоненты.

{
  "@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",
...

Такие средства, как Azure IoT Обозреватель и конструктор шаблонов устройств IoT Central, помечают автономный интерфейс, например термостат в качестве компонента по умолчанию.

На следующем снимке экрана показано, как модель отображается в средстве Обозреватель Azure IoT:

Снимок экрана: компонент по умолчанию в средстве обозревателя Интернета вещей Azure.

На следующем снимке экрана показано, как модель отображается как компонент по умолчанию в конструкторе шаблонов устройств IoT Central. Выберите Просмотр удостоверения, чтобы просмотреть DTMI модели:

Снимок экрана: модель Термостата в средстве конструктора шаблонов устройств IoT Central.

Идентификатор модели хранится в свойстве двойника устройства, как показано на следующем снимке экрана:

Снимок экрана: средство Обозреватель Интернета вещей Azure, в котором показан идентификатор модели в свойстве цифрового двойника.

Модель DTDL без компонентов является полезным упрощением для устройства или модуля IoT Edge с единым набором телеметрии, свойств и команд. Модель, которая не использует компоненты, упрощает превращение существующего устройства или модуля в устройство или модуль IoT Plug and Play. Вы создаете модель DTDL, которая описывает реальное устройство или модуль, без необходимости определять какие-либо компоненты.

Совет

Модуль может быть модулем устройства или модулем IoT Edge.

Повторное использование

Существует два способа повторного использования определений интерфейсов.

  • Использование нескольких компонентов в модели для ссылки на другие определения интерфейса.
  • Использование наследования для расширения существующих определений интерфейса.

Несколько компонентов

Компоненты позволяют создать интерфейс модели в виде сборки других интерфейсов.

Например, интерфейс термостата определяется как модель. Этот интерфейс можно включить в качестве одного или нескольких компонентов при определении Модели контроллера температуры. В следующем примере эти компоненты называются thermostat1 и thermostat2.

Для модели DTDL с несколькими компонентами существует два или более раздела компонентов. Каждый раздел имеет значение @type, установленное на Component, и явно ссылается на схему, как показано в следующем фрагменте кода.

{
  "@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."
    }
  ]
}

Эта модель содержит три компонента, определенные в разделе содержимого, — два компонента Thermostat и компонент DeviceInformation. В раздел содержимого также входят свойства, данные телеметрии и определения команд.

На следующих снимках экрана показано, как эта модель отображается в IoT Central. Свойства, данные телеметрии и определения команд в контроллере температуры отображаются в компоненте по умолчанию верхнего уровня. Свойства, данные телеметрии и определения команд для каждого термостата отображаются в определениях компонентов:

Снимок экрана, показывающий шаблон устройства контроллера температуры в IoT Central.

Снимок экрана, показывающий компоненты термостата в устройстве контроллера температуры в IoT Central.

Сведения о написании кода устройства, взаимодействующего с компонентами, см. в Руководстве для разработчика устройств IoT Plug and Play.

Сведения о написании кода службы, взаимодействующего с компонентами на устройстве, см. в руководстве разработчика службы Интернета вещей самонастраивающийся.

Наследование

Наследование позволяет повторно использовать возможности в базовых интерфейсах для расширения возможностей интерфейса. Например, несколько моделей устройств могут совместно использовать такие общие возможности, как серийный номер:

Схема, демонстрирующая пример наследования в модели устройства. Интерфейс Термостата и интерфейс контроллера потока совместно используют возможности базового интерфейса.

В следующем фрагменте кода показана модель DTML, которая использует ключевое слово extends для определения отношения наследования, показанного на предыдущей схеме:

[
  {
    "@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
      }
    ]
  }
]

На следующем снимке экрана показана эта модель в среде шаблона устройства IoT Central:

Снимок экрана: наследование интерфейса в IoT Central.

При написании кода на стороне устройства или службы коду не нужно ничего специального для работы с унаследованными интерфейсами. В примере, приведенном в этом разделе, код устройства сообщает серийный номер, как если бы он был частью интерфейса термостата.

Советы

При создании модели можно сочетать компоненты и наследование. На следующей схеме показана модель thermostat, наследуемая от интерфейса baseDevice. Интерфейс содержит компонент baseDevice, который сам наследуется от другого интерфейса:

Схема, показывающая модель, которая использует как компоненты, так и наследование.

В следующем фрагменте кода показана модель DTML, которая использует ключевые слова extends и component для определения отношения наследования и использования компонентов, показанных на предыдущей схеме:

[
  {
    "@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"
      }
    ]
  }
]

Типы данных

Используйте типы данных для определения телеметрии, свойств и параметров команды. Типы данных могут быть простыми или сложными. Сложные типы данных используют примитивы или другие сложные типы. Максимальная глубина для сложных типов составляет пять уровней.

Примитивные типы

В следующей таблице показан набор типов-примитивов, которые можно использовать.

Тип-примитив Description
boolean Логическое значение.
date Полная дата, как определено в разделе 5.6 RFC 3339
dateTime Дата и время, как определено в RFC 3339
double 8-байтовая плавающая точка в формате IEEE
duration Длительность в формате ISO 8601
float 4-байтовая плавающая точка в формате IEEE
integer 4-байтовое целое число со знаком
long 8-байтовое целое число со знаком
string Строка UTF8
time Полное время, как определено в разделе 5.6 RFC 3339

В следующем фрагменте кода показан пример определения телеметрии, где используется тип double в поле schema:

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

Сложные типы данных

Сложные типы данных являются одним из массивов, перечисления, карты, объекта или одного из геопространственных типов.

Массивы

Массив — это индексируемый тип данных, в котором все элементы имеют один и тот же тип. Тип элемента может быть примитивным или сложным типом.

В следующем фрагменте кода показан пример определения телеметрии, где используется тип Array в поле schema. Элементы массива являются логическими:

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

Перечисления

Перечисление описывает тип с набором именованных меток, которые сопоставляются со значениями. Значения могут быть либо целыми числами, либо строками, но метки всегда являются строками.

В следующем фрагменте кода показан пример определения телеметрии, где используется тип Enum в поле schema. Значения в перечислении являются целыми числами:

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

Карты

Карта — это тип с парами "ключ-значение", в котором все значения имеют одинаковый тип. Ключ на карте должен быть строкой. Значения на карте могут быть любого типа, включая другой сложный тип.

В следующем фрагменте кода показан пример определения свойства, где используется тип Map в поле schema. Значения на карте являются строками:

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

Объект

Тип объекта состоит из именованных полей. Типы полей в карте объектов могут быть простыми или сложными типами.

В следующем фрагменте кода показан пример определения телеметрии, где используется тип Object в поле schema. Поля в объекте бывают типов dateTime, duration и string:

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

Геопространственные типы

DTDL предоставляет набор геопространственных типов, основанных на GeoJSON, для моделирования структур географических данных: point, multiPoint, lineString, multiLineString, polygon и multiPolygon. Эти типы являются предопределенными вложенными структурами массивов, объектов и перечислений.

В следующем фрагменте кода показан пример определения телеметрии, где используется тип point в поле schema:

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

Поскольку геопространственные типы основаны на массивах, их нельзя использовать в определениях свойств.

Семантические типы

Тип данных определения свойства или телеметрии указывает формат данных, обмениваемых устройством со службой. Семантический тип предоставляет сведения о телеметрии и свойствах, которые приложение может использовать для определения способа обработки или отображения значения. Каждый семантический тип имеет одну или несколько связанных единиц. Например, градусы Цельсия и Фаренгейта являются единицами для семантического типа температуры. Панели мониторинга и аналитика IoT Central могут использовать сведения о семантическом типе для определения способа построения данных телеметрии или значений свойств и единиц отображения. Сведения об использовании средства синтаксического анализа модели для чтения семантических типов см. в разделе Знакомство со средством синтаксического анализа моделей цифровых двойников.

В следующем фрагменте кода показан пример определения телеметрии, включающего сведения о семантическом типе. Семантический тип Temperature добавляется в массив @type, а значение unit, degreeCelsius — одна из допустимых единиц для семантического типа:

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

Локализация

Приложения, такие как IoT Central, используют сведения в модели для динамического создания пользовательского интерфейса на основе данных, которыми обмениваются устройства IoT Plug and Play. Например, плитки на панели мониторинга могут отображать имена и описания для телеметрии, свойств и команд.

Необязательные поля description и displayName в модели содержат строки, предназначенные для использования в пользовательском интерфейсе. Эти поля могут содержать локализованные строки, которые приложение может использовать для отображения локализованного пользовательского интерфейса.

В следующем фрагменте кода показан пример определения телеметрии температуры, включающий локализованные строки:

{
  "@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"
}

Добавление локализованных строк является необязательным. В следующем примере используется только один язык по умолчанию:

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

Жизненный цикл и средства

Четыре этапа жизненного цикла модели устройства: создание, публикация, использование и управление версиями.

Автор

Модели устройств DTML — это документы JSON, которые можно создавать в текстовом редакторе. Однако в IoT Central можно использовать среду с графическим интерфейсом шаблона устройства, чтобы создать модель DTML. В IoT Central можно делать следующее.

  • Создавать интерфейсы, определяющие свойства, данные телеметрии и команды.
  • Использовать компоненты для объединения нескольких интерфейсов.
  • Определять отношения наследования между интерфейсами.
  • Импорт и экспорт файлов модели DTML.

Дополнительные сведения см. в статье Определение типа нового устройства IoT в приложении Azure IoT Central.

Существует расширение разработки DTDL для VS Code.

Чтобы установить расширение DTDL для VS Code, перейдите на страницу редактора DTDL для Visual Studio Code. Можно также выполнить поиск DTDL в представлении Extensions (Расширения) в VS Code.

При установке расширения используйте его для создания файлов модели DTDL в VS Code:

  • Расширение обеспечивает проверку синтаксиса в файлах модели DTDL, выделяя ошибки, как показано на следующем снимке экрана:

    Снимок экрана: проверка модели DTDL в VS Code.

  • При редактировании моделей DTDL используйте IntelliSense и автозавершение:

    Снимок экрана: intellisense для моделей DTDL в VS Code.

  • Создайте новый интерфейс DTDL. Команда DTDL: Create Interface создает JSON-файл с новым интерфейсом. Интерфейс включает примеры данных телеметрии, свойств и команд.

Использование

Приложения, такие как IoT Central, используют модели устройств. В IoT Central модель является частью шаблона устройства, который описывает возможности устройства. IoT Central использует шаблон устройства для динамического создания пользовательского интерфейса для устройства, включая панели мониторинга и аналитику.

Примечание.

IoT Central определяет некоторые расширения на языке DTDL. Дополнительные сведения см . в расширении IoT Central.

Пользовательское решение может использовать средство синтаксического анализа моделей цифровых двойников для понимания возможностей устройства, реализующего модель. Дополнительные сведения см. в статье Использование моделей IoT Plug and Play в решении IoT.

Версия

Чтобы гарантировать, что устройства и серверные решения, использующие модели, продолжают работать, опубликованные модели являются неизменяемыми.

DTMI включает номер версии, который можно использовать для создания нескольких версий модели. Устройства и серверные решения могут использовать определенную версию, для использования которой они предназначены.

IoT Central реализует дополнительные правила управления версиями для моделей устройств. Если создать версию шаблона устройства и его модели в IoT Central, можно перенести устройства из предыдущих версий в более поздние версии. Однако перенесенные устройства не могут использовать новые возможности без обновления встроенного ПО. Чтобы узнать больше, ознакомьтесь с разделом Изменение шаблона устройства.

Публикация

По состоянию на февраль 2024 года программа сертифицированных устройств Azure была прекращена. Поэтому корпорация Майкрософт больше не принимает отправки моделей DTDL врепозиторий моделей IoT Plug and Play Azure.

Если вы хотите настроить собственный репозиторий моделей, вы можете использовать репозиторий инструментов моделей IoT Для Интернета вещей Azure. Этот репозиторий содержит код для dmr-client средства CLI, который может проверять, импортировать и расширять модели DTDL. Это средство также позволяет индексировать репозитории модели, которые соответствуют соглашениям репозитория моделей устройств.

Предельные значения и ограничения

В следующем списке приведены некоторые ключевые ограничения для моделей:

  • В настоящее время максимальная глубина массивов, карт и объектов составляет пять уровней.
  • Нельзя использовать массивы в определениях свойств.
  • Расширять интерфейсы можно до 10 уровней.
  • Интерфейс может расширять не более двух других интерфейсов.
  • Компонент не может содержать другой компонент.

Следующие шаги

Теперь, когда вы узнали о моделировании устройств, вот несколько дополнительных ресурсов: