设备孪生 是存储设备状态信息的 JSON 文档,包括元数据、配置和条件。 Azure IoT 中心为连接到 IoT 中心的每个设备维护设备孪生。
注释
本文中所述的功能仅在 IoT 中心的标准层中可用。 有关基本层和标准/免费 IoT 中心层的详细信息,请参阅 为解决方案选择正确的 IoT 中心层和大小。
本文介绍:
- 设备孪生的结构: 标记、 所需属性和 报告属性。
- 设备和后端应用程序可以在设备数字孪生上执行的操作。
使用设备孪生可以:
将特定于设备的元数据存储在云中。 例如,自动售货机的位置。
报告当前状态信息,例如设备应用中的可用功能和条件。 例如,设备是通过手机网络还是 WiFi 连接到 IoT 中心。
在设备应用和后端应用之间同步长时间运行的工作流的状态。 例如,当后端应用指定要安装的新固件版本时,设备应用将报告更新过程的各个阶段。
查询设备元数据、配置或状态。
有关使用报告的属性、设备到云消息或文件上传的详细信息,请参阅 设备到云的通信指南。
有关使用所需属性、直接方法或云到设备消息的详细信息,请参阅 云到设备的通信指南。
设备克隆
设备孪生存储与设备相关的信息,这些信息如下:
设备应用和后端应用可用于同步设备条件和配置。
解决方案后端可用于查询和针对长时间运行的操作。
设备孪生的生命周期链接到其相应的 设备标识。 在 IoT 中心,当设备标识被创建或删除时,设备孪生也将被隐式创建或删除。
设备孪生是一个包含以下内容的 JSON 文档:
标记。 后端应用可从中读取和写入的 JSON 文档的一部分。 设备应用看不到标记。
所需属性。 与报告的属性一起用于同步设备配置或条件。 后端应用可以设置所需的属性,设备应用可以读取它们。 设备应用还可以接收所需属性中更改的通知。
报告的属性。 与所需属性一起用于同步设备配置或条件。 设备应用可以设置报告的属性,后端应用可以读取和查询它们。
设备标识属性。 设备孪生 JSON 文档的根包含从对应设备标识中提取的只读属性,这些属性存储在标识注册表中。 不包括
connectionStateUpdatedTime和generationId属性。
以下示例显示了设备孪生 JSON 文档:
{
"deviceId": "devA",
"etag": "AAAAAAAAAAc=",
"status": "enabled",
"statusReason": "provisioned",
"statusUpdateTime": "0001-01-01T00:00:00",
"connectionState": "connected",
"lastActivityTime": "2015-02-30T16:24:48.789Z",
"cloudToDeviceMessageCount": 0,
"authenticationType": "sas",
"x509Thumbprint": {
"primaryThumbprint": null,
"secondaryThumbprint": null
},
"version": 2,
"tags": {
"deploymentLocation": {
"building": "43",
"floor": "1"
}
},
"properties": {
"desired": {
"telemetryConfig": {
"sendFrequency": "5m"
},
"$metadata" : {...},
"$version": 1
},
"reported": {
"telemetryConfig": {
"sendFrequency": "5m",
"status": "success"
},
"batteryLevel": 55,
"$metadata" : {...},
"$version": 4
}
}
}
根对象包含设备标识属性,tags 的容器对象,以及包括属性 reported 和 desired 的容器对象。 容器properties包含$metadata和$version部分中介绍的一些只读元素(和)。
报告的属性示例
在上一个示例中,设备孪生包含一个 batteryLevel 所报告的属性。 此属性使能够根据上次报告的电池电量为基础查询、操作设备。 其他示例包括设备应用报告设备功能或连接选项。
注释
报告的属性简化了您对属性最后已知值感兴趣的使用场景。 如果要以时间戳事件序列(如时序)的形式处理设备遥测,请使用 设备到云的消息 。
所需属性示例
在前面的示例中, telemetryConfig 解决方案后端和设备应用使用设备孪生的期望属性和报告属性来同步此设备的遥测配置。 例如:
后端应用程序使用预期的配置值来设置目标属性。 下面是包含所需属性集的文档部分:
"desired": { "telemetryConfig": { "sendFrequency": "5m" }, ... },如果设备已连接,设备应用将立即收到更改的通知。 如果尚未连接,设备应用在连接时会遵循设备重新连接流程。 然后,设备应用报告更新的配置(或通过使用
status属性报告错误情况)。 下面是报告属性的一部分:"reported": { "telemetryConfig": { "sendFrequency": "5m", "status": "success" } ... }后端应用通过 查询 设备孪生来跟踪跨多个设备配置操作的结果。
注释
前面的代码片段是一种编码设备配置及其状态的方法,针对可读性进行优化。 IoT 中心不会对设备孪生中期望的和报告的属性施加特定的架构。
可以使用数字孪生体来同步长时间运行的作业,例如固件更新。 有关如何使用属性跨设备同步和跟踪长时间运行的操作的详细信息,请参阅 使用所需属性配置设备。
后端操作
后端系统在设备孪生上运行操作,使用通过 HTTPS 公开的以下原子操作:
按 ID 检索设备孪生。 此操作返回设备孪生文档,包括标记、所需的系统属性和报告的系统属性。
部分更新设备孪生。 此操作将设备孪生中的标记或所需属性进行部分更新。 部分更新表示为添加或更新任何属性的 JSON 文档。 将删除设置为
null的属性。 以下示例创建一个具有值{"newProperty": "newValue"}的新所需属性,覆盖现有existingProperty值"otherNewValue"并删除otherOldProperty。 没有对现有所需属性或标记进行其他更改:{ "properties": { "desired": { "newProperty": { "nestedProperty": "newValue" }, "existingProperty": "otherNewValue", "otherOldProperty": null } } }替换所需属性。 此操作完全覆盖所有现有的期望属性,并替换新的 JSON 文档
properties/desired。替换标记。 此操作将完全覆盖所有现有标记,并用新的 JSON 文档替换
tags。接收孪生通知。 此操作会在修改数字孪生时通知。 若要接收设备孪生更改通知,IoT 解决方案需要创建路由并将数据源设置为等于 twinChangeEvents。 默认情况下,不存在此类路由,因此不会发送孪生通知。 如果更改率过高,或者出于其他原因(如内部故障),IoT 中心可能会只发送一个包含所有更改的通知。 因此,如果应用程序需要所有中间状态的可靠审核和日志记录,则应使用设备到云的消息。 若要详细了解孪生通知消息中返回的属性和正文,请参阅 Nontelemetry 事件架构。
上述所有操作都支持乐观并发,并要求ServiceConnect权限,如控制对IoT中心的访问中定义。
除了这些操作,解决方案后端还可以:
使用类似于 SQL 的 IoT 中心查询语言查询设备孪生。
使用 作业对大型设备孪生集执行操作。
设备操作
设备应用在设备孪生上使用以下原子操作:
检索设备孪生信息。 此操作返回当前连接设备的设备孪生体文档(包括期望和报告的系统属性)。 (设备应用看不到标记。
部分更新已报告的属性。 此作允许对当前连接的设备的报告属性进行部分更新。
观察期望的属性。 当前连接的设备可以选择在发生更新时收到所需属性的通知。
上述所有操作都需要 DeviceConnect 权限,如 控制对 IoT Hub 的访问中定义。
借助 Azure IoT 设备 SDK,可以轻松地从多种语言和平台使用上述作。 有关 IoT 中心基元的所需属性同步的详细信息,请参阅 设备重新连接流。
标记和属性格式
标记、所需属性和报告属性是具有以下限制的 JSON 对象:
键:JSON 对象中的所有键都是 UTF-8 编码的、区分大小写的,长度最长为 1 KB。 允许的字符不包括 UNICODE 控制字符(C0 和 C1 段),以及
.、$和 SP。注释
消息路由中使用的 IoT 中心查询不支持空格或以下任何字符作为密钥名称的一部分:
()<>@,;:\"/?={}值:JSON 对象中的所有值可以是以下 JSON 类型:布尔值、数字、字符串、对象。 还支持数组。
整数的最小值可以为 -4503599627370496,最大值为 4503599627370495。
字符串值经过 UTF-8 编码,最大长度可以为 4 KB。
深度:标记、所需属性和报告属性中 JSON 对象的最大深度为 10。 例如,以下对象有效:
{ ... "tags": { "one": { "two": { "three": { "four": { "five": { "six": { "seven": { "eight": { "nine": { "ten": { "property": "value" } } } } } } } } } } }, ... }
设备孪生大小
IoT 中心对 tags 的值强制实施 8 KB 大小限制,并对 properties/desired 和 properties/reported 的值分别实施 32 KB 大小限制。 这些总计不包括只读元素,例如 $version 和 $metadata/$lastUpdated。
孪生大小按如下方式计算:
IoT Hub 累积计算每个属性键和值的长度并进行相加。
属性键被视为 UTF8 编码的字符串。
简单属性值被视为 UTF8 编码的字符串、数值(8 字节)或布尔值(4 字节)。
UTF8 编码字符串的大小通过计算所有字符(不包括 UNICODE 控制字符(段 C0 和 C1)来计算。
复杂属性值(嵌套对象)是根据它们包含的属性键和属性值的聚合大小计算的。
IoT 中心会拒绝所有导致tags、properties/desired或properties/reported文档大小超过限制的操作,并报告错误。
设备孪生元数据
IoT 中心维护设备孪生所需属性和报告属性中每个 JSON 对象的上次更新的时间戳。 时间戳采用 UTC 格式,采用 ISO8601 格式 YYYY-MM-DDTHH:MM:SS.mmmZ进行编码。
例如:
{
...
"properties": {
"desired": {
"telemetryConfig": {
"sendFrequency": "5m"
},
"$metadata": {
"telemetryConfig": {
"sendFrequency": {
"$lastUpdated": "2016-03-30T16:24:48.789Z"
},
"$lastUpdated": "2016-03-30T16:24:48.789Z"
},
"$lastUpdated": "2016-03-30T16:24:48.789Z"
},
"$version": 23
},
"reported": {
"telemetryConfig": {
"sendFrequency": "5m",
"status": "success"
},
"batteryLevel": "55%",
"$metadata": {
"telemetryConfig": {
"sendFrequency": {
"$lastUpdated": "2016-03-31T16:35:48.789Z"
},
"status": {
"$lastUpdated": "2016-03-31T16:35:48.789Z"
},
"$lastUpdated": "2016-03-31T16:35:48.789Z"
},
"batteryLevel": {
"$lastUpdated": "2016-04-01T16:35:48.789Z"
},
"$lastUpdated": "2016-04-01T16:24:48.789Z"
},
"$version": 123
}
}
...
}
此信息保存在每个级别(而不仅仅是 JSON 结构的叶),以保留删除对象键的更新。
乐观并发
标签、目标属性和报告属性都支持乐观并发。 如果需要保证孪生属性更新的顺序,请考虑通过在发送下一个更新之前等待报告的属性回调在应用程序级别实现同步。
根据etag,设备孪生具有一个 ETag 属性,该属性表示孪生的 JSON 表示形式。 可以在解决方案后端的条件更新作中使用 etag 属性来确保一致性。 此属性是确保涉及 tags 容器的作中的一致性的唯一选项。
设备孪生的期望属性和报告属性也有一个 $version 值,其值保证是递增的。 与 ETag 类似,可以使用版本属性来强制实施更新的一致性。 例如,报告属性的设备应用或所需属性的后端应用。
当观察代理(例如观察所需属性的设备应用)必须调和检索操作的结果与更新通知之间的竞争情况时,版本也非常有用。 “ 设备重新连接流”部分 提供了详细信息。
设备重新连接流程
IoT 中心不会保留已断开连接设备的所需属性更新通知。 随后,连接的设备除了订阅更新通知外,还必须检索完整的所需属性文档。 鉴于更新通知与完全检索之间存在竞争的可能性,必须确保以下流程:
- 设备应用连接到 IoT 中心。
- 设备应用程序订阅通知,以获取目标属性的更新。
- 设备应用检索所需属性的完整文档。
设备应用可以忽略小于 $version 或等于完整检索文档版本的所有通知。 这种方法是可能的,因为 IoT 中心保证版本始终递增。
后续步骤
若要试用本文中所述的一些概念,请参阅以下 IoT 中心文章: