你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

遥测、属性和命令有效负载

设备模型定义:

  • 设备发送到服务的遥测数据。
  • 设备与服务同步的属性。
  • 服务在设备上调用的命令。

提示

Azure IoT Central 是遵循即插即用约定的服务。 在 IoT Central 中,设备模型是设备模板的一部分。 IoT Central 目前支持具有 IoT Central 扩展DTDL v2。 IoT Central 应用程序需要接收 UTF-8 编码的 JSON 数据。

本文介绍设备为 DTDL 设备模型中定义的遥测、属性和命令发送和接收的 JSON 有效负载。

本文不介绍遥测、属性和命令有效负载的每个可能类型,但示例说明了关键类型。

每个示例都演示了设备模型中的一个代码片段,该代码片段定义了类型和示例 JSON 有效负载,以说明设备应如何与即插即用感知服务(如 IoT Central)交互。

本文中的示例 JSON 代码片段使用 数字孪生定义语言 (DTDL) V2。 还有一些 IoT Central 使用的 DTDL 扩展。

有关显示其中某些有效负载正在使用的示例设备代码,请参阅连接在 Linux 或 Windows 上运行的示例IoT 即插即用设备应用程序,以IoT 中心教程创建客户端应用程序并将其连接到 Azure IoT Central 应用程序教程。

查看原始数据

如果使用 IoT Central,可以查看设备发送到应用程序的原始数据。 此视图可用于排除发送自设备的有效负载的问题。 若要查看设备正在发送的原始数据:

  1. 从“设备”页导航到设备

  2. 选择“原始数据”选项卡:

    Screenshot that shows the raw data view.

    在此视图中,你可以选择要显示的列,并设置要查看的时间范围。 “未建模数据”列显示设备中与设备模板中的任何属性或遥测定义不匹配的数据。

有关更多故障排除提示,请参阅 排查设备中的数据未显示在 Azure IoT Central 中的原因。

遥测

若要了解有关 DTDL 遥测命名规则的详细信息,请参阅 DTDL > 遥测。 不能使用 _ 字符启动遥测名称。

不要使用以下名称创建遥测类型。 IoT Central 在内部使用这些保留名称。 如果尝试使用这些名称,IoT Central 将忽略数据:

  • EventEnqueuedUtcTime
  • EventProcessedUtcTime
  • PartitionId
  • EventHub
  • User
  • $metadata
  • $version

组件中的遥测

如果在组件中定义遥测,请使用设备模型中定义的组件名称添加名为 $.sub 的自定义消息属性。 若要了解详细信息,请参阅教程:连接IoT 即插即用多个组件设备应用程序。 本教程演示如何使用不同的编程语言从组件发送遥测数据。

重要

若要正确显示来自 IoT Edge 模块中承载的组件的遥测数据,请使用 IoT Edge 版本 1.2.4 或更高版本。 如果使用早期版本,来自 IoT Edge 模块中组件的遥测数据会显示为“_unmodeleddata”

继承接口中的遥测

如果遥测是在继承接口中定义的,则设备会发送遥测数据,就好像在根接口中定义一样。 给定以下设备模型:

[
    {
        "@id": "dtmi:contoso:device;1",
        "@type": "Interface",
        "contents": [
            {
                "@type": [
                    "Property",
                    "Cloud",
                    "StringValue"
                ],
                "displayName": {
                    "en": "Device Name"
                },
                "name": "DeviceName",
                "schema": "string"
            }
        ],
        "displayName": {
            "en": "Contoso Device"
        },
        "extends": [
            "dtmi:contoso:sensor;1"
        ],
        "@context": [
            "dtmi:iotcentral:context;2",
            "dtmi:dtdl:context;2"
        ]
    },
    {
        "@context": [
            "dtmi:iotcentral:context;2",
            "dtmi:dtdl:context;2"
        ],
        "@id": "dtmi:contoso:sensor;1",
        "@type": [
            "Interface",
            "NamedInterface"
        ],
        "contents": [
            {
                "@type": [
                    "Telemetry",
                    "NumberValue"
                ],
                "displayName": {
                    "en": "Meter Voltage"
                },
                "name": "MeterVoltage",
                "schema": "double"
            }
        ],
        "displayName": {
            "en": "Contoso Sensor"
        },
        "name": "ContosoSensor"
    }
]

设备使用以下有效负载发送计量电压遥测数据。 设备不包括有效负载中的接口名称:

{
    "MeterVoltage": 5.07
}

基元类型

本部分介绍设备可以流式传输的基元遥测类型示例。

设备模型中的以下代码片段显示 boolean 遥测类型的定义:

{
  "@type": "Telemetry",
  "displayName": {
    "en": "BooleanTelemetry"
  },
  "name": "BooleanTelemetry",
  "schema": "boolean"
}

设备客户端应该以 JSON 形式发送遥测,如下例所示:

{ "BooleanTelemetry": true }

设备模型中的以下代码片段显示 string 遥测类型的定义:

{
  "@type": "Telemetry",
  "displayName": {
    "en": "StringTelemetry"
  },
  "name": "StringTelemetry",
  "schema": "string"
}

设备客户端应该以 JSON 形式发送遥测,如下例所示:

{ "StringTelemetry": "A string value - could be a URL" }

设备模型中的以下代码片段显示 integer 遥测类型的定义:

{
  "@type": "Telemetry",
  "displayName": {
    "en": "IntegerTelemetry"
  },
  "name": "IntegerTelemetry",
  "schema": "integer"
}

设备客户端应该以 JSON 形式发送遥测,如下例所示:

{ "IntegerTelemetry": 23 }

设备模型中的以下代码片段显示 double 遥测类型的定义:

{
  "@type": "Telemetry",
  "displayName": {
    "en": "DoubleTelemetry"
  },
  "name": "DoubleTelemetry",
  "schema": "double"
}

设备客户端应该以 JSON 形式发送遥测,如下例所示:

{ "DoubleTelemetry": 56.78 }

设备模型中的以下代码片段显示 dateTime 遥测类型的定义:

{
  "@type": "Telemetry",
  "displayName": {
    "en": "DateTimeTelemetry"
  },
  "name": "DateTimeTelemetry",
  "schema": "dateTime"
}

设备客户端应该以 JSON 形式发送遥测,如下例所示。DateTime 类型必须是 ISO 8061 格式:

{ "DateTimeTelemetry": "2020-08-30T19:16:13.853Z" }

设备模型中的以下代码片段显示 duration 遥测类型的定义:

{
  "@type": "Telemetry",
  "displayName": {
    "en": "DurationTelemetry"
  },
  "name": "DurationTelemetry",
  "schema": "duration"
}

设备客户端应该以 JSON 形式发送遥测,如下例所示。持续时间必须是 ISO 8601 格式:

{ "DurationTelemetry": "PT10H24M6.169083011336625S" }

复杂类型

本部分演示设备可以流式传输的复杂遥测类型的示例。

设备模型中的以下代码片段显示 Enum 遥测类型的定义:

{
  "@type": "Telemetry",
  "displayName": {
    "en": "EnumTelemetry"
  },
  "name": "EnumTelemetry",
  "schema": {
    "@type": "Enum",
    "displayName": {
      "en": "Enum"
    },
    "valueSchema": "integer",
    "enumValues": [
      {
        "displayName": {
          "en": "Item1"
        },
        "enumValue": 0,
        "name": "Item1"
      },
      {
        "displayName": {
          "en": "Item2"
        },
        "enumValue": 1,
        "name": "Item2"
      },
      {
        "displayName": {
          "en": "Item3"
        },
        "enumValue": 2,
        "name": "Item3"
      }
    ]
  }
}

设备客户端应该以 JSON 形式发送遥测,如下所示。 值可能为 012,它们在 IoT Central 中显示为 Item1Item2Item3

{ "EnumTelemetry": 1 }

设备模型中的以下代码片段显示 Object 遥测类型的定义。 此对象具有类型为 dateTimeintegerEnum 的三个字段:

{
  "@type": "Telemetry",
  "displayName": {
    "en": "ObjectTelemetry"
  },
  "name": "ObjectTelemetry",
  "schema": {
    "@type": "Object",
    "displayName": {
      "en": "Object"
    },
    "fields": [
      {
        "displayName": {
          "en": "Property1"
        },
        "name": "Property1",
        "schema": "dateTime"
      },
      {
        "displayName": {
          "en": "Property2"
        },
        "name": "Property2",
        "schema": "integer"
      },
      {
        "displayName": {
          "en": "Property3"
        },
        "name": "Property3",
        "schema": {
          "@type": "Enum",
          "displayName": {
            "en": "Enum"
          },
          "valueSchema": "integer",
          "enumValues": [
            {
              "displayName": {
                "en": "Item1"
              },
              "enumValue": 0,
              "name": "Item1"
            },
            {
              "displayName": {
                "en": "Item2"
              },
              "enumValue": 1,
              "name": "Item2"
            },
            {
              "displayName": {
                "en": "Item3"
              },
              "enumValue": 2,
              "name": "Item3"
            }
          ]
        }
      }
    ]
  }
}

设备客户端应该以 JSON 形式发送遥测,如下所示。 DateTime 类型必须符合 ISO 8061 标准。 Property3 值可能为 01,它们在 IoT Central 中显示为 Item1Item2Item3

{
  "ObjectTelemetry": {
      "Property1": "2020-09-09T03:36:46.195Z",
      "Property2": 37,
      "Property3": 2
  }
}

设备模型中的以下代码片段显示 vector 遥测类型的定义:

{
  "@type": "Telemetry",
  "displayName": {
    "en": "VectorTelemetry"
  },
  "name": "VectorTelemetry",
  "schema": "vector"
}

设备客户端应该以 JSON 形式发送遥测,如下例所示:

{
  "VectorTelemetry": {
    "x": 74.72395045538597,
    "y": 74.72395045538597,
    "z": 74.72395045538597
  }
}

设备模型中的以下代码片段显示 geopoint 遥测类型的定义:

{
  "@type": "Telemetry",
  "displayName": {
    "en": "GeopointTelemetry"
  },
  "name": "GeopointTelemetry",
  "schema": "geopoint"
}

注意

地理点架构类型是到 DTDL 的 IoT Central 扩展一部分。 IoT Central 目前支持 geopoint 架构类型和 location 语义类型,以实现后向兼容性

设备客户端应该以 JSON 形式发送遥测,如下所示。 IoT Central 在地图上以 pin 的形式显示值:

{
  "GeopointTelemetry": {
    "lat": 47.64263,
    "lon": -122.13035,
    "alt": 0
  }
}

事件和状态类型

本部分显示设备发送到 IoT Central 应用程序的遥测事件和状态的示例。

注意

事件状态架构类型是到 DTDL 的 IoT Central 扩展一部分。

设备模型中的以下代码片段显示 integer 事件类型的定义:

{
  "@type": [
    "Telemetry",
    "Event"
  ],
  "displayName": {
    "en": "IntegerEvent"
  },
  "name": "IntegerEvent",
  "schema": "integer"
}

设备客户端应该以 JSON 形式发送事件数据,如下例所示:

{ "IntegerEvent": 74 }

设备模型中的以下代码片段显示 integer 状态类型的定义:

{
  "@type": [
    "Telemetry",
    "State"
  ],
  "displayName": {
    "en": "IntegerState"
  },
  "name": "IntegerState",
  "schema": {
    "@type": "Enum",
    "valueSchema": "integer",
    "enumValues": [
      {
        "displayName": {
          "en": "Level1"
        },
        "enumValue": 1,
        "name": "Level1"
      },
      {
        "displayName": {
          "en": "Level2"
        },
        "enumValue": 2,
        "name": "Level2"
      },
      {
        "displayName": {
          "en": "Level3"
        },
        "enumValue": 3,
        "name": "Level3"
      }
    ]
  }
}

设备客户端应该以 JSON 形式发送状态,如下例所示。 整数状态值可能为 123

{ "IntegerState": 2 }

属性

若要了解有关 DTDL 属性命名规则的详细信息,请参阅 DTDL > 属性。 不能使用 _ 字符启动遥测名称。

组件中的属性

如果该属性是在组件中定义的,请将该属性包装在组件名称中。 以下示例将 maxTempSinceLastReboot 设置在 thermostat2 组件中。 该标记 __t 指示此部分定义组件:

{
  "thermostat2" : {  
    "__t" : "c",  
    "maxTempSinceLastReboot" : 38.7
    } 
}

若要了解详细信息,请参阅教程:创建客户端应用程序并将其连接到 Azure IoT Central 应用程序

基元类型

本部分介绍设备发送到服务的基本属性类型的示例。

设备模型中的以下代码片段显示 boolean 属性类型的定义:

{
  "@type": "Property",
  "displayName": {
    "en": "BooleanProperty"
  },
  "name": "BooleanProperty",
  "schema": "boolean",
  "writable": false
}

设备客户端应发送 JSON 有效负载,将其作为设备孪生中报告的属性,类似于以下示例:

{ "BooleanProperty": false }

设备模型中的以下代码片段显示 long 属性类型的定义:

{
  "@type": "Property",
  "displayName": {
    "en": "LongProperty"
  },
  "name": "LongProperty",
  "schema": "long",
  "writable": false
}

设备客户端应发送 JSON 有效负载,将其作为设备孪生中报告的属性,类似于以下示例:

{ "LongProperty": 439 }

设备模型中的以下代码片段显示 date 属性类型的定义:

{
  "@type": "Property",
  "displayName": {
    "en": "DateProperty"
  },
  "name": "DateProperty",
  "schema": "date",
  "writable": false
}

设备客户端应发送 JSON 有效负载,将其作为设备孪生中报告的属性,类似于以下示例。 Date 类型必须符合 ISO 8061 标准:

{ "DateProperty": "2020-05-17" }

设备模型中的以下代码片段显示 duration 属性类型的定义:

{
  "@type": "Property",
  "displayName": {
    "en": "DurationProperty"
  },
  "name": "DurationProperty",
  "schema": "duration",
  "writable": false
}

设备客户端应发送 JSON 有效负载,将其作为设备孪生中报告的属性,类似于以下示例 - 持续时间必须符合 ISO 8601 Duration 标准:

{ "DurationProperty": "PT10H24M6.169083011336625S" }

设备模型中的以下代码片段显示 float 属性类型的定义:

{
  "@type": "Property",
  "displayName": {
    "en": "FloatProperty"
  },
  "name": "FloatProperty",
  "schema": "float",
  "writable": false
}

设备客户端应发送 JSON 有效负载,将其作为设备孪生中报告的属性,类似于以下示例:

{ "FloatProperty": 1.9 }

设备模型中的以下代码片段显示 string 属性类型的定义:

{
  "@type": "Property",
  "displayName": {
    "en": "StringProperty"
  },
  "name": "StringProperty",
  "schema": "string",
  "writable": false
}

设备客户端应发送 JSON 有效负载,将其作为设备孪生中报告的属性,类似于以下示例:

{ "StringProperty": "A string value - could be a URL" }

复杂类型

本部分显示了设备发送到服务的复杂属性类型的示例。

设备模型中的以下代码片段显示 Enum 属性类型的定义:

{
  "@type": "Property",
  "displayName": {
    "en": "EnumProperty"
  },
  "name": "EnumProperty",
  "writable": false,
  "schema": {
    "@type": "Enum",
    "displayName": {
      "en": "Enum"
    },
    "valueSchema": "integer",
    "enumValues": [
      {
        "displayName": {
          "en": "Item1"
        },
        "enumValue": 0,
        "name": "Item1"
      },
      {
        "displayName": {
          "en": "Item2"
        },
        "enumValue": 1,
        "name": "Item2"
      },
      {
        "displayName": {
          "en": "Item3"
        },
        "enumValue": 2,
        "name": "Item3"
      }
    ]
  }
}

设备客户端应发送 JSON 有效负载,将其作为设备孪生中报告的属性,类似于以下示例。 值可能为 01,它们在 IoT Central 中显示为 Item1Item2Item3

{ "EnumProperty": 1 }

设备模型中的以下代码片段显示 Object 属性类型的定义。 此对象具有类型为 stringinteger 的两个字段:

{
  "@type": "Property",
  "displayName": {
    "en": "ObjectProperty"
  },
  "name": "ObjectProperty",
  "writable": false,
  "schema": {
    "@type": "Object",
    "displayName": {
      "en": "Object"
    },
    "fields": [
      {
        "displayName": {
          "en": "Field1"
        },
        "name": "Field1",
        "schema": "integer"
      },
      {
        "displayName": {
          "en": "Field2"
        },
        "name": "Field2",
        "schema": "string"
      }
    ]
  }
}

设备客户端应发送 JSON 有效负载,将其作为设备孪生中报告的属性,类似于以下示例:

{
  "ObjectProperty": {
    "Field1": 37,
    "Field2": "A string value"
  }
}

设备模型中的以下代码片段显示 vector 属性类型的定义:

{
  "@type": "Property",
  "displayName": {
    "en": "VectorProperty"
  },
  "name": "VectorProperty",
  "schema": "vector",
  "writable": false
}

设备客户端应发送 JSON 有效负载,将其作为设备孪生中报告的属性,类似于以下示例:

{
  "VectorProperty": {
    "x": 74.72395045538597,
    "y": 74.72395045538597,
    "z": 74.72395045538597
  }
}

设备模型中的以下代码片段显示 geopoint 属性类型的定义:

{
  "@type": "Property",
  "displayName": {
    "en": "GeopointProperty"
  },
  "name": "GeopointProperty",
  "schema": "geopoint",
  "writable": false
}

注意

地理点架构类型是到 DTDL 的 IoT Central 扩展一部分。 IoT Central 目前支持 geopoint 架构类型和 location 语义类型,以实现后向兼容性

设备客户端应发送 JSON 有效负载,将其作为设备孪生中报告的属性,类似于以下示例:

{
  "GeopointProperty": {
    "lat": 47.64263,
    "lon": -122.13035,
    "alt": 0
  }
}

可写属性类型

本部分演示设备从服务接收的可写属性类型的示例。

如果在组件中定义了可写属性,则所需属性消息包含组件名称。 以下示例展示了请求设备更新 thermostat2 组件中 targetTemperature 的消息。 该标记 __t 指示此部分定义组件:

{
  "thermostat2": {
    "targetTemperature": {
      "value": 57
    },
    "__t": "c"
  },
  "$version": 3
}

若要了解详细信息,请参阅连接IoT 即插即用多个组件设备应用程序

设备或模块应通过发送报告的属性来确认已接收到属性。 报告的属性应包括:

  • value - 属性的实际值(通常是接收到的值,但设备可能决定报告不同的值)。
  • ac - 使用 HTTP 状态代码的确认代码。
  • av - 引用所需属性的 $version 的确认版本。 可在所需的属性 JSON 有效负载中找到该值。
  • ad - 可选确认说明。

若要详细了解这些字段,请参阅IoT 即插即用约定>确认响应

设备模型中的以下代码片段显示了一个可写 string 属性类型的定义:

{
  "@type": "Property",
  "displayName": {
    "en": "StringPropertyWritable"
  },
  "name": "StringPropertyWritable",
  "writable": true,
  "schema": "string"
}

设备从服务接收以下有效负载:

{  
  "StringPropertyWritable": "A string from IoT Central", "$version": 7
}

设备在处理更新后应将以下 JSON 有效负载发送到服务。 此消息包括从服务接收的原始更新的版本号。

提示

如果服务为 IoT Central,则会在收到此消息时将属性 标记为在 UI 中同步:

{
  "StringPropertyWritable": {
    "value": "A string from IoT Central",
    "ac": 200,
    "ad": "completed",
    "av": 7
  }
}

设备模型中的以下代码片段显示了一个可写 Enum 属性类型的定义:

{
  "@type": "Property",
  "displayName": {
    "en": "EnumPropertyWritable"
  },
  "name": "EnumPropertyWritable",
  "writable": true,
  "schema": {
    "@type": "Enum",
    "displayName": {
      "en": "Enum"
    },
    "valueSchema": "integer",
    "enumValues": [
      {
        "displayName": {
          "en": "Item1"
        },
        "enumValue": 0,
        "name": "Item1"
      },
      {
        "displayName": {
          "en": "Item2"
        },
        "enumValue": 1,
        "name": "Item2"
      },
      {
        "displayName": {
          "en": "Item3"
        },
        "enumValue": 2,
        "name": "Item3"
      }
    ]
  }
}

设备从服务接收以下有效负载:

{  
  "EnumPropertyWritable":  1 , "$version": 10
}

设备在处理更新后应将以下 JSON 有效负载发送到服务。 此消息包括从服务接收的原始更新的版本号。

提示

如果服务为 IoT Central,则会在收到此消息时将属性 标记为在 UI 中同步:

{
  "EnumPropertyWritable": {
    "value": 1,
    "ac": 200,
    "ad": "completed",
    "av": 10
  }
}

命令

若要了解有关 DTDL 命令命名规则的详细信息,请参阅 DTDL > 命令。 不能使用 _ 字符启动命令名称。

如果在组件中定义了命令,则设备接收的命令的名称包括组件名称。 例如,如果命令名称为 getMaxMinReport,并且组件名称为 thermostat2,则设备会收到请求,执行名称为 thermostat2*getMaxMinReport 的命令。

设备模型中的以下代码片段显示没有参数并且不要求设备返回任何内容的命令的定义:

{
  "@type": "Command",
  "displayName": {
    "en": "CommandBasic"
  },
  "name": "CommandBasic"
}

设备在请求中接收到一个空的有效负载,并且应在响应中返回一个空的有效负载,同时使用 200 HTTP 响应代码指示成功。

设备模型中的以下代码片段显示具有整数参数并且要求设备返回整数值的命令的定义:

{
  "@type": "Command",
  "request": {
    "@type": "CommandPayload",
    "displayName": {
      "en": "RequestParam"
    },
    "name": "RequestParam",
    "schema": "integer"
  },
  "response": {
    "@type": "CommandPayload",
    "displayName": {
      "en": "ResponseParam"
    },
    "name": "ResponseParam",
    "schema": "integer"
  },
  "displayName": {
    "en": "CommandSimple"
  },
  "name": "CommandSimple"
}

设备接收一个整数值作为请求有效负载。 设备应返回一个整数值作为响应有效负载,并返回 200 HTTP 响应代码以指示成功。

设备模型中的以下代码片段显示具有对象参数并且要求设备返回对象的命令的定义。 此示例中,两个对象都有整数和字符串字段:

{
  "@type": "Command",
  "request": {
    "@type": "CommandPayload",
    "displayName": {
      "en": "RequestParam"
    },
    "name": "RequestParam",
    "schema": {
      "@type": "Object",
      "displayName": {
        "en": "Object"
      },
      "fields": [
        {
          "displayName": {
            "en": "Field1"
          },
          "name": "Field1",
          "schema": "integer"
        },
        {
          "displayName": {
            "en": "Field2"
          },
          "name": "Field2",
          "schema": "string"
        }
      ]
    }
  },
  "response": {
    "@type": "CommandPayload",
    "displayName": {
      "en": "ResponseParam"
    },
    "name": "ResponseParam",
    "schema": {
      "@type": "Object",
      "displayName": {
        "en": "Object"
      },
      "fields": [
        {
          "displayName": {
            "en": "Field1"
          },
          "name": "Field1",
          "schema": "integer"
        },
        {
          "displayName": {
            "en": "Field2"
          },
          "name": "Field2",
          "schema": "string"
        }
      ]
    }
  },
  "displayName": {
    "en": "CommandComplex"
  },
  "name": "CommandComplex"
}

以下代码片段显示发送到设备的示例请求有效负载:

{ "Field1": 56, "Field2": "A string value" }

以下代码片段显示发送自设备的示例响应有效负载。 使用 200 HTTP 响应代码指示成功:

{ "Field1": 87, "Field2": "Another string value" }

提示

IoT Central 有自己的约定,用于实现 长时间运行的命令脱机命令

后续步骤

了解设备有效负载后,建议接下来的步骤是阅读 设备开发人员指南