Соглашения IoT Plug and Play
Когда устройства IoT Plug and Play обмениваются сообщениями с центром Интернета вещей, к ним применимы требования набора соглашений. IoT Plug and Play устройства используют протокол MQTT для взаимодействия с Центр Интернета вещей, amQP поддерживается Центр Интернета вещей и доступна в некоторых пакетах SDK для устройств.
Устройство может включать модули или быть реализовано в IoT Edge модуле, размещенном в среде выполнения IoT Edge.
Вы описываете данные телеметрии, свойства и команды, которые устройство IoT Plug and Play реализует с помощью моделиDTDL версии 2. В этой статье рассматриваются два типа моделей:
- Нет компонентов — модель без компонентов. Модель объявляет данные телеметрии, свойства и команды в качестве элементов верхнего уровня в разделе содержимого главного интерфейса. В Обозревателе Интернета вещей Azure эта модель отображается как отдельный компонент по умолчанию.
- Несколько компонентов — модель, состоящая из двух или более интерфейсов. Основной интерфейс, который отображается как компонент по умолчанию с данными телеметрии, свойствами и командами. Один или несколько интерфейсов, объявленных как компоненты с дополнительными данными телеметрии, свойствами и командами.
Дополнительные сведения см. в статье Руководство по созданию моделей IoT Plug and Play.
Определение модели
Чтобы объявить реализуемую модель, устройство или модуль IoT Plug and Play вносит идентификатор модели в пакет подключения MQTT, добавляя model-id
в поле USERNAME
.
Для идентификации модели, реализуемой устройством или модулем, служба может получить идентификатор модели из:
- Поля двойника устройства
modelId
. - Поля цифрового двойника
$metadata.$model
. - Уведомления об изменениях цифровых двойников.
Телеметрия
- Данные телеметрии, отправляемые с устройства без компонента, не нуждаются в дополнительных метаданных. Система добавляет свойство
dt-dataschema
. - Телеметрия, отправленная с устройства с помощью компонентов, должна добавить имя компонента в сообщение телеметрии.
- При использовании MQTT добавьте
$.sub
свойство с именем компонента в раздел телеметрии, система добавляетdt-subject
свойство . - При использовании AMQP добавьте
dt-subject
свойство с именем компонента в качестве заметки к сообщению.
Примечание
Для телеметрии из компонентов требуется по одному сообщению на каждый компонент.
Свойства только для чтения
Свойство только для чтения задается устройством и передается внутреннему приложению.
Образец бескомпонентного свойства только для чтения
Устройство или модуль может отправлять любой допустимый КОД JSON, соответствующий правилам DTDL V2.
DTDL, определяющий свойство в интерфейсе:
{
"@context": "dtmi:dtdl:context;2",
"@id": "dtmi:example: Thermostat;1",
"@type": "Interface",
"contents": [
{
"@type": "Property",
"name": "temperature",
"schema": "double"
}
]
}
Пример полезных данных передаваемого свойства:
"reported" :
{
"temperature" : 21.3
}
Пример использования многокомпонентного свойства только для чтения
Устройство или модуль должны добавить маркер {"__t": "c"}
, чтобы указать, что элемент ссылается на компонент.
DTDL, ссылающийся на компонент:
{
"@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, определяющий компонент:
{
"@context": "dtmi:dtdl:context;2",
"@id": "dtmi:com:example:Thermostat;1",
"@type": "Interface",
"contents": [
{
"@type": "Property",
"name": "temperature",
"schema": "double"
}
]
}
Пример полезных данных передаваемого свойства:
"reported": {
"thermostat1": {
"__t": "c",
"temperature": 21.3
}
}
Свойства, доступные для записи
Свойство для записи может быть задано серверным приложением и отправлено на устройство.
Устройство или модуль должны подтвердить, что они получили свойство, отправив передаваемое свойство. Передаваемое свойство должно включать в себя:
value
— фактическое значение свойства (обычно полученное значение, однако устройство может передать другое значение).ac
— код подтверждения, использующий код состояния HTTP.av
— версия подтверждения, относящаяся к$version
требуемого свойства. Это значение можно найти в полезных данных JSON требуемого свойства.ad
— необязательное описание подтверждения.
Ответы на подтверждение
При создании отчетов о свойствах, доступных для записи, устройство должно создать сообщение подтверждения, используя четыре поля, описанные выше, чтобы указать фактическое состояние устройства, как описано в следующей таблице:
Status(ac) | Версия(av) | Value(value) | Описание(av) |
---|---|---|---|
200 | Требуемая версия | Требуемое значение | Допустимое значение требуемого свойства |
202 | Требуемая версия | Значение, принятое устройством | Требуемое значение свойства принято, выполняется обновление (должно завершиться с 200) |
203 | 0 | Значение, заданное устройством | Свойство, заданное с устройства, не отражающее желаемое |
400 | Требуемая версия | Фактическое значение, используемое устройством | Требуемое значение свойства не принято |
500 | Требуемая версия | Фактическое значение, используемое устройством | Исключение при применении свойства |
Когда устройство запускается, оно должно запросить двойника этого устройства и проверить наличие обновлений свойств, доступных для записи. Если версия свойства, доступного для записи, увеличилась, когда устройство находилось в автономном режиме, устройство должно отправить ответ о передаваемом свойстве, чтобы подтвердить, что обновление получено.
Когда устройство запускается в первый раз, оно может отправить начальное значение для сообщаемого свойства, если оно не получает начальное требуемое свойство из Центра Интернета вещей. В этом случае устройство может отправить значение по умолчанию с av
в 0
и ac
в 203
. Пример:
"reported": {
"targetTemperature": {
"value": 20.0,
"ac": 203,
"av": 0,
"ad": "initialize"
}
}
Устройство может использовать передаваемое свойство для предоставления других сведений концентратору. Например, устройство может реагировать на ряд выполняющихся сообщений, таких как:
"reported": {
"targetTemperature": {
"value": 35.0,
"ac": 202,
"av": 3,
"ad": "In-progress - reporting current temperature"
}
}
Когда устройство достигает целевой температуры, оно отправляет следующее сообщение:
"reported": {
"targetTemperature": {
"value": 20.0,
"ac": 200,
"av": 4,
"ad": "Reached target temperature"
}
}
Устройство может сообщить об ошибке, например:
"reported": {
"targetTemperature": {
"value": 120.0,
"ac": 500,
"av": 3,
"ad": "Target temperature out of range. Valid range is 10 to 99."
}
}
Тип объекта
Если свойство, доступное для записи, определено как объект , служба должна отправить на устройство полный объект. Устройство должно подтвердить обновление, отправив в службу достаточно информации, чтобы служба поняла, как устройство действовало при обновлении. Этот ответ может включать следующее:
- Весь объект.
- Только поля, обновленные устройством.
- Подмножество полей.
Для крупных объектов рекомендуется свести к минимуму размер объекта, включенного в подтверждение.
В следующем примере показано доступное для записи свойство, определенное как , с четырьмя Object
полями:
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
}
Чтобы обновить это записываемое свойство, отправьте полный объект из службы, который выглядит следующим образом:
{
"samplingRange": {
"startTime": "2021-08-17T12:53:00.000Z",
"lastTime": "2021-08-17T14:54:00.000Z",
"count": 100,
"errorCount": 5
}
}
Устройство отвечает подтверждением, которое выглядит как в следующем примере:
{
"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
}
}
}
Пример бескомпонентного записываемого свойства
Когда устройство получает несколько требуемых свойств в одной полезной нагрузке, оно может отправлять ответы сообщаемого свойства через несколько полезных данных или объединять ответы в одну полезную нагрузку.
Устройство или модуль может отправлять любой допустимый КОД JSON, соответствующий правилам DTDL V2.
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
}
]
}
Пример полезных данных требуемого свойства:
"desired" :
{
"targetTemperature" : 21.3,
"targetHumidity" : 80,
"$version" : 3
}
Пример первых полезных данных передаваемого свойства:
"reported": {
"targetTemperature": {
"value": 21.3,
"ac": 200,
"av": 3,
"ad": "complete"
}
}
Пример вторых полезных данных передаваемого свойства:
"reported": {
"targetHumidity": {
"value": 80,
"ac": 200,
"av": 3,
"ad": "complete"
}
}
Примечание
Вы можете объединить эти две полезные данные сообщаемого свойства в одну полезную нагрузку.
Пример использования многокомпонентного записываемого свойства
Устройство или модуль должны добавить маркер {"__t": "c"}
, чтобы указать, что элемент ссылается на компонент.
Маркер отправляется только для обновлений свойств, определенных в компоненте. Обновления свойств, определенных в компоненте по умолчанию, не включают маркер, см. раздел Пример свойства без записи компонента.
Когда устройство получает несколько сообщаемых свойств в одной полезной нагрузке, оно может отправлять ответы сообщаемого свойства через несколько полезных данных или объединять ответы в одну полезную нагрузку.
Устройство или модуль должны подтвердить, что они получили свойства, отправив передаваемые свойства:
DTDL, ссылающийся на компонент:
{
"@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, определяющий компонент:
{
"@context": "dtmi:dtdl:context;2",
"@id": "dtmi:com:example:Thermostat;1",
"@type": "Interface",
"contents": [
{
"@type": "Property",
"name": "targetTemperature",
"schema": "double",
"writable": true
}
]
}
Пример полезных данных требуемого свойства:
"desired": {
"thermostat1": {
"__t": "c",
"targetTemperature": 21.3,
"targetHumidity": 80,
"$version" : 3
}
}
Пример первых полезных данных передаваемого свойства:
"reported": {
"thermostat1": {
"__t": "c",
"targetTemperature": {
"value": 23,
"ac": 200,
"av": 3,
"ad": "complete"
}
}
}
Пример вторых полезных данных передаваемого свойства:
"reported": {
"thermostat1": {
"__t": "c",
"targetHumidity": {
"value": 80,
"ac": 200,
"av": 3,
"ad": "complete"
}
}
}
Примечание
Вы можете объединить эти две полезные данные сообщаемого свойства в одну полезную нагрузку.
Команды
Ни один из интерфейсов компонентов не использует имя команды без префикса.
На устройстве или модуле в интерфейсах с несколькими компонентами имена команд используются в следующем формате: componentName*commandName
.
Дальнейшие действия
Теперь, когда вы узнали о соглашениях IoT Plug and Play, ознакомьтесь с другими ресурсами: