在 IoT 中心内了解并使用模块孪生Understand and use module twins in IoT Hub

本文假设读者事先已阅读了解并在 IoT 中心内使用设备孪生This article assumes you've read understand and use device twins in IoT Hub first. 在 IoT 中心的每个设备标识下,最多可以创建 20 个模块标识。In IoT Hub, under each device identity, you can create up to 20 module identities. 每个模块标识隐式生成模块孪生。Each module identity implicitly generates a module twin. 模块孪生与设备孪生类似,是存储模块状态信息(例如元数据、配置和条件)的 JSON 文档。Similar to device twins, module twins are JSON documents that store module state information including metadata, configurations, and conditions. Azure IoT 中心为连接到 IoT 中心的每个模块保留一个模块孪生。Azure IoT Hub maintains a module twin for each module that you connect to IoT Hub.

在设备端,可以使用 IoT 中心设备 SDK 创建模块,其中每个模块与 IoT 中心建立独立连接。On the device side, the IoT Hub device SDKs enable you to create modules where each one opens an independent connection to IoT Hub. 通过此功能,可对设备上的不同组件使用不同的命名空间。This functionality enables you to use separate namespaces for different components on your device. 例如,某个自动贩卖机包含三个不同的传感器。For example, you have a vending machine that has three different sensors. 每个传感器由公司的不同部门控制。Each sensor is controlled by different departments in your company. 可为每个传感器创建一个模块。You can create a module for each sensor. 这样,每个部门只能向他们控制的传感器发送作业或直接方法,避免发生冲突和用户失误。This way, each department is only able to send jobs or direct methods to the sensor that they control, avoiding conflicts and user errors.

模块标识和模块孪生提供的功能与设备标识和设备孪生相同,但前者的粒度更细。Module identity and module twin provide the same capabilities as device identity and device twin but at a finer granularity. 这种更高的粒度级可让有能力的设备(例如基于操作系统的设备,或管理多个组件的固件设备)隔离其中每个组件的配置和状态。This finer granularity enables capable devices, such as operating system-based devices or firmware devices managing multiple components, to isolate configuration and conditions for each of those components. 与包含模块化软件组件的 IoT 设备结合使用时,模块标识和模块孪生能够提供管理关注点分离。Module identity and module twins provide a management separation of concerns when working with IoT devices that have modular software components. 推出模块孪生的正式版后,我们将会支持模块孪生级别的所有设备孪生功能。We aim at supporting all the device twin functionality at module twin level by module twin general availability.

Note

本文中所述的功能仅可在 IoT 中心的标准层中使用。The features described in this article are only available in the standard tier of IoT hub. 有关基本和标准 IoT 中心层的详细信息,请参阅如何选择合适的 IoT 中心层For more information about the basic and standard IoT Hub tiers, see How to choose the right IoT Hub tier.

本文介绍:This article describes:

  • 模块孪生的结构:标记、所需的属性和报告的属性 。The structure of the module twin: tags, desired and reported properties.
  • 模块和后端可在模块孪生上执行的操作。The operations that the modules and back ends can perform on module twins.

有关使用报告的属性、设备到云的消息或文件上传的指导,请参阅设备到云的通信指南Refer to Device-to-cloud communication guidance for guidance on using reported properties, device-to-cloud messages, or file upload. 有关使用所需的属性、直接方法或云到设备的消息的指导,请参阅云到设备的通信指南Refer to Cloud-to-device communication guidance for guidance on using desired properties, direct methods, or cloud-to-device messages.

模块孪生Module twins

模块孪生存储具有以下用途的模块相关信息:Module twins store module-related information that:

  • 设备和 IoT 中心上的模块可以使用这些信息来同步模块状态和配置。Modules on the device and IoT Hub can use to synchronize module conditions and configuration.
  • 解决方案后端可以使用这些信息来查询和定位长时间运行的操作。The solution back end can use to query and target long-running operations.

模块孪生的生命周期链接到相应的模块标识The lifecycle of a module twin is linked to the corresponding module identity. 在 IoT 中心创建或删除模块标识时,将隐式创建和删除模块孪生。Modules twins are implicitly created and deleted when a module identity is created or deleted in IoT Hub.

模块孪生是一个 JSON 文档,其中包含:A module twin is a JSON document that includes:

  • 标记Tags. 解决方案后端可从中读取和写入数据的 JSON 文档的某个部分。A section of the JSON document that the solution back end can read from and write to. 标记对设备上的模块不可见。Tags are not visible to modules on the device. 设置的标记用于查询目的。Tags are set for querying purpose.
  • 所需的属性Desired properties. 与报告的属性结合使用,同步模块配置或状态。Used along with reported properties to synchronize module configuration or conditions. 解决方案后端可设置所需的属性,并且模块应用可进行读取。The solution back end can set desired properties, and the module app can read them. 此外,当所需的属性发生更改时,模块应用可收到通知。The module app can also receive notifications of changes in the desired properties.
  • 报告的属性Reported properties. 与所需的属性结合使用,同步模块配置或状态。Used along with desired properties to synchronize module configuration or conditions. 模块应用可设置报告的属性,并且解决方案后端可进行读取和查询。The module app can set reported properties, and the solution back end can read and query them.
  • 模块标识属性Module identity properties. 模块孪生 JSON 文档的根包含标识注册表中存储的相应模块标识的只读属性。The root of the module twin JSON document contains the read-only properties from the corresponding module identity stored in the identity registry.

设备孪生的体系结构表示形式

以下示例显示了一个模块孪生 JSON 文档:The following example shows a module twin JSON document:

{
    "deviceId": "devA",
    "moduleId": "moduleA",
    "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": {
        "$etag": "123",
        "deploymentLocation": {
            "building": "43",
            "floor": "1"
        }
    },
    "properties": {
        "desired": {
            "telemetryConfig": {
                "sendFrequency": "5m"
            },
            "$metadata" : {...},
            "$version": 1
        },
        "reported": {
            "telemetryConfig": {
                "sendFrequency": "5m",
                "status": "success"
            },
            "batteryLevel": 55,
            "$metadata" : {...},
            "$version": 4
        }
    }
}

根对象中包含模块标识属性,以及 tagsreporteddesired 属性的容器对象。In the root object are the module identity properties, and container objects for tags and both reported and desired properties. properties 容器包含一些只读元素($metadata$etag$version),模块孪生元数据 and Optimistic concurrency 部分描述了这些元素。The properties container contains some read-only elements ($metadata, $etag, and $version) described in the Module twin metadata and Optimistic concurrency sections.

报告属性示例Reported property example

在上面的示例中,模块孪生包含模块应用报告的 batteryLevel 属性。In the previous example, the module twin contains a batteryLevel property that is reported by the module app. 使用此属性可以根据上次报告的电池电量水平查询和操作模块。This property makes it possible to query and operate on modules based on the last reported battery level. 其他示例包括让模块应用报告模块功能或连接选项。Other examples include the module app reporting module capabilities or connectivity options.

Note

报告的属性如何简化解决方案后端获取属性最后一个已知值的方案。Reported properties simplify scenarios where the solution back end is interested in the last known value of a property. 如果解决方案后端需要以带时间戳事件序列(例如时间序列)的形式处理模块遥测数据,可以使用设备到云的消息Use device-to-cloud messages if the solution back end needs to process module telemetry in the form of sequences of timestamped events, such as time series.

所需属性示例Desired property example

在上面的示例中,解决方案后端和模块应用使用 telemetryConfig 模块孪生的所需和报告属性来同步此模块的遥测配置。In the previous example, the telemetryConfig module twin desired and reported properties are used by the solution back end and the module app to synchronize the telemetry configuration for this module. 例如:For example:

  1. 解决方案后端使用所需配置值设置所需属性。The solution back end sets the desired property with the desired configuration value. 下面是包含所需属性集的文档的一部分:Here is the portion of the document with the desired property set:

    ...
    "desired": {
        "telemetryConfig": {
            "sendFrequency": "5m"
        },
        ...
    },
    ...
    
  2. 连接后或者首次重新连接时,模块应用会立即收到更改通知。The module app is notified of the change immediately if connected, or at the first reconnect. 然后,模块应用报告更新的配置(或使用 status 属性报告错误状态)。The module app then reports the updated configuration (or an error condition using the status property). 下面是报告属性的一部分:Here is the portion of the reported properties:

    "reported": {
        "telemetryConfig": {
            "sendFrequency": "5m",
            "status": "success"
        }
        ...
    }
    
  3. 解决方案后端可以通过查询模块孪生,跟踪多个模块上的配置操作结果。The solution back end can track the results of the configuration operation across many modules, by querying module twins.

Note

为便于阅读,上述代码片段示例经过优化,演示了为模块配置及其状态进行编码的一种方式。The preceding snippets are examples, optimized for readability, of one way to encode a module configuration and its status. IoT 中心不会对模块孪生中的所需属性和报告属性施加特定的架构。IoT Hub does not impose a specific schema for the module twin desired and reported properties in the module twins.

后端操作Back-end operations

解决方案后端使用以下通过 HTTPS 公开的原子操作对模块孪生执行操作:The solution back end operates on the module twin using the following atomic operations, exposed through HTTPS:

  • 按 ID 检索模块孪生Retrieve module twin by ID. 此操作返回模块孪生文档,包括标记、所需的系统属性和报告的系统属性。This operation returns the module twin document, including tags and desired and reported system properties.

  • 部分更新模块孪生Partially update module twin. 解决方案后端可以使用此操作部分更新模块孪生中的标记或所需属性。This operation enables the solution back end to partially update the tags or desired properties in a module twin. 部分更新以 JSON 文档的形式表示,可添加或更新任何属性。The partial update is expressed as a JSON document that adds or updates any property. 将删除设置为 null 的属性。Properties set to null are removed. 以下示例创建值为 {"newProperty": "newValue"} 的新所需属性,将现有值 existingProperty 覆盖为 "otherNewValue",并删除 otherOldPropertyThe following example creates a new desired property with value {"newProperty": "newValue"}, overwrites the existing value of existingProperty with "otherNewValue", and removes otherOldProperty. 不会对现有的所需属性或标记进行其他任何更改:No other changes are made to existing desired properties or tags:

    {
        "properties": {
            "desired": {
                "newProperty": {
                    "nestedProperty": "newValue"
                },
                "existingProperty": "otherNewValue",
                "otherOldProperty": null
            }
        }
    }
    
  • 替换所需属性Replace desired properties. 解决方案后端可以使用此操作完全覆盖所有现有的所需属性,并使用新 JSON 文档替代 properties/desiredThis operation enables the solution back end to completely overwrite all existing desired properties and substitute a new JSON document for properties/desired.

  • 替换标记Replace tags. 解决方案后端可以使用此操作完全覆盖所有现有标记,并使用新 JSON 文档替代 tagsThis operation enables the solution back end to completely overwrite all existing tags and substitute a new JSON document for tags.

  • 接收孪生通知Receive twin notifications. 此操作允许解决方案后端在修改孪生时收到通知。This operation allows the solution back end to be notified when the twin is modified. 为此,IoT 解决方案需要创建一个路由,并且将“数据源”设置为等于 twinChangeEventsTo do so, your IoT solution needs to create a route and to set the Data Source equal to twinChangeEvents. 默认情况下,不会发送孪生通知,即,无此类路由预先存在。By default, no twin notifications are sent, that is, no such routes pre-exist. 如果更改速率太高,或由于其他原因(例如内部故障),IoT 中心可能会只发送一个包含所有更改的通知。If the rate of change is too high, or for other reasons such as internal failures, the IoT Hub might send only one notification that contains all changes. 因此,如果应用程序需要可靠地审核和记录所有中间状态,则应使用设备到云消息。Therefore, if your application needs reliable auditing and logging of all intermediate states, you should use device-to-cloud messages. 孪生通知消息包括属性和正文。The twin notification message includes properties and body.

    • 属性Properties

      NameName ValueValue
      $content-type$content-type application/jsonapplication/json
      $iothub-enqueuedtime$iothub-enqueuedtime 发送通知的时间Time when the notification was sent
      $iothub-message-source$iothub-message-source twinChangeEventstwinChangeEvents
      $content-encoding$content-encoding utf-8utf-8
      deviceIddeviceId 设备 IDID of the device
      moduleIdmoduleId 模块 的 IDID of the module
      hubNamehubName IoT 中心的名称Name of IoT Hub
      operationTimestampoperationTimestamp ISO8601 操作时间戳ISO8601 timestamp of operation
      iothub-message-schemaiothub-message-schema deviceLifecycleNotificationdeviceLifecycleNotification
      opTypeopType “replaceTwin”或“updateTwin”"replaceTwin" or "updateTwin"

      消息系统属性以 $ 符号作为前缀。Message system properties are prefixed with the $ symbol.

    • 正文Body

      本部分包括 JSON 格式的所有孪生更改。This section includes all the twin changes in a JSON format. 它使用与修补程序相同的格式,不同的是它可以包含所有孪生节:标记、properties.reported、properties.desired,并且它包含“$metadata”元素。It uses the same format as a patch, with the difference that it can contain all twin sections: tags, properties.reported, properties.desired, and that it contains the “$metadata” elements. 例如,For example,

      {
        "properties": {
            "desired": {
                "$metadata": {
                    "$lastUpdated": "2016-02-30T16:24:48.789Z"
                },
                "$version": 1
            },
            "reported": {
                "$metadata": {
                    "$lastUpdated": "2016-02-30T16:24:48.789Z"
                },
                "$version": 1
            }
        }
      }
      

上述所有操作均支持乐观并发,并且需要控制对 IoT 中心的访问文章中定义的 ServiceConnect 权限 。All the preceding operations support Optimistic concurrency and require the ServiceConnect permission, as defined in the Control Access to IoT Hub article.

除了上述操作以外,解决方案后端还可以使用类似于 SQL 的 IoT 中心查询语言查询模块孪生。In addition to these operations, the solution back end can query the module twins using the SQL-like IoT Hub query language.

模块操作Module operations

模块应用使用以下原子操作对模块孪生执行操作:The module app operates on the module twin using the following atomic operations:

  • 检索模块孪生Retrieve module twin. 此操作返回当前连接的模块的模块孪生文档(包括标记、所需的系统属性和报告的系统属性)。This operation returns the module twin document (including tags and desired and reported system properties) for the currently connected module.
  • 部分更新报告属性Partially update reported properties. 使用此操作可以部分更新当前连接的模块的报告属性。This operation enables the partial update of the reported properties of the currently connected module. 此操作使用的 JSON 更新格式与解决方案后端用于部分更新所需属性的格式相同。This operation uses the same JSON update format that the solution back end uses for a partial update of desired properties.
  • 观察所需属性Observe desired properties. 当前连接的模块可以选择在所需属性发生更新时接收通知。The currently connected module can choose to be notified of updates to the desired properties when they happen. 模块收到的更新格式与解决方案后端执行的更新格式相同(部分或完全替换)。The module receives the same form of update (partial or full replacement) executed by the solution back end.

上述所有操作都需要控制对 IoT 中心的访问一文中定义的 ModuleConnect 权限。All the preceding operations require the ModuleConnect permission, as defined in the Control Access to IoT Hub article.

借助 Azure IoT 设备 SDK,可通过多种语言和平台轻松使用上述操作。The Azure IoT device SDKs make it easy to use the preceding operations from many languages and platforms.

标记和属性格式Tags and properties format

标记、所需的属性和报告的属性是具有以下限制的 JSON 对象:Tags, desired properties, and reported properties are JSON objects with the following restrictions:

  • JSON 对象中的所有键是区分大小写的 64 字节 UTF-8 UNICODE 字符串。All keys in JSON objects are case-sensitive 64 bytes UTF-8 UNICODE strings. 允许的字符不包括 UNICODE 控制字符(段 C0 和 C1)以及 .、SP 和 $Allowed characters exclude UNICODE control characters (segments C0 and C1), and ., SP, and $.

  • JSON 对象中的所有值可采用以下 JSON 类型:布尔值、数字、字符串、对象。All values in JSON objects can be of the following JSON types: boolean, number, string, object. 不允许数组。Arrays are not allowed. 最大整数值为 4503599627370495,而最小整数值为 -4503599627370496。The maximum value for integers is 4503599627370495 and the minimum value for integers is -4503599627370496.

  • 标记、所需属性和报告属性中的所有 JSON 对象的最大嵌套深度为 5 层。All JSON objects in tags, desired, and reported properties can have a maximum depth of 5. 例如,以下对象是有效的:For instance, the following object is valid:

    {
        ...
        "tags": {
            "one": {
                "two": {
                    "three": {
                        "four": {
                            "five": {
                                "property": "value"
                            }
                        }
                    }
                }
            }
        },
        ...
    }
    
  • 所有字符串的值的长度最多为 512 个字节。All string values can be at most 512 bytes in length.

模块孪生大小Module twin size

IoT 中心对 tagsproperties/desiredproperties/reported(不包括只读元素)的各个总值强制实施 8KB 大小限制。IoT Hub enforces an 8KB size limitation on each of the respective total values of tags, properties/desired, and properties/reported, excluding read-only elements. 该大小的计算考虑到了所有字符,但不包括 UNICODE 控制字符(段 C0 和 C1),以及出现在字符串常量外部的空格。The size is computed by counting all characters, excluding UNICODE control characters (segments C0 and C1) and spaces that are outside of string constants. IoT 中心拒绝将这些文档的大小增加到超出限制的所有操作,在这种情况下还会返回错误。IoT Hub rejects with an error all operations that would increase the size of those documents above the limit.

模块孪生元数据Module twin metadata

IoT 中心保留模块孪生所需属性和报告属性中每个 JSON 对象的上次更新时间戳。IoT Hub maintains the timestamp of the last update for each JSON object in module twin desired and reported properties. 时间戳采用 UTC,以 ISO8601 格式编码YYYY-MM-DDTHH:MM:SS.mmmZThe timestamps are in UTC and encoded in the ISO8601 format YYYY-MM-DDTHH:MM:SS.mmmZ. 例如:For example:

{
    ...
    "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": "5m",
                    "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 结构的叶级别)保留此信息,以便保留删除了对象键的更新。This information is kept at every level (not just the leaves of the JSON structure) to preserve updates that remove object keys.

乐观并发Optimistic concurrency

标记、所需的属性和报告的属性都支持乐观并发。Tags, desired, and reported properties all support optimistic concurrency. 标记包含一个符合 RFC7232 规范的 ETag,它是标记的 JSON 表示形式。Tags have an ETag, as per RFC7232, that represents the tag's JSON representation. 可在解决方案后端上的条件更新操作中使用 ETag 来确保一致性。You can use ETags in conditional update operations from the solution back end to ensure consistency.

模块孪生所需的属性和报告的属性不包含 ETag,但包含一个保证可递增的 $version 值。Module twin desired and reported properties do not have ETags, but have a $version value that is guaranteed to be incremental. 更新方可以使用类似于 ETag 的版本来强制实施更新一致性。Similarly to an ETag, the version can be used by the updating party to enforce consistency of updates. 例如,报告的属性的模块应用,或者所需的属性的解决方案后端。For example, a module app for a reported property or the solution back end for a desired property.

当监视代理(例如,监视所需属性的模块应用)必须协调检索操作结果与更新通知之间的资源争用时,版本也很有用。Versions are also useful when an observing agent (such as the module app observing the desired properties) must reconcile races between the result of a retrieve operation and an update notification. 设备重新连接流 部分提供了详细信息。The section Device reconnection flow provides more information.

后续步骤Next steps

要尝试本文中介绍的一些概念,请参阅以下 IoT 中心教程:To try out some of the concepts described in this article, see the following IoT Hub tutorials: