View a markdown version of this page

Device Shadow 服务文档 - AWS IoT Core

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

Device Shadow 服务文档

Device Shadow 服务遵守 JSON 规范下的所有规则。值、对象和数组均存储在设备的影子文档中。

影子文档示例

设备影子服务使用 REST API 或 MQTT Pub/Sub 消息在更新、获取和删除操作中使用这些文档。

请求状态文档

请求状态文档具有以下格式:

{ "state": { "desired": { "attribute1": integer2, "attribute2": "string2", ... "attributeN": boolean2 }, "reported": { "attribute1": integer1, "attribute2": "string1", ... "attributeN": boolean1 } }, "clientToken": "token", "version": version }
  • state - 更新仅影响指定字段。通常,您将使用 desired 或 reported 属性,但不能在同一请求中同时使用这两个属性。

    • desired - 请求在设备中更新的状态属性和值。

    • reported - 设备报告的状态属性和值。

  • clientToken - 如果使用,您可以通过客户端令牌匹配请求和相应的响应。

  • version - 如果使用,仅当指定的版本与 Device Shadow 服务拥有的最新版本相符时,该服务才会处理更新。

响应状态文档

响应状态文档具有以下格式,具体取决于响应类型。

/accepted 响应状态文档

{ "state": { "desired": { "attribute1": integer2, "attribute2": "string2", ... "attributeN": boolean2 } }, "metadata": { "desired": { "attribute1": { "timestamp": timestamp }, "attribute2": { "timestamp": timestamp }, ... "attributeN": { "timestamp": timestamp } } }, "timestamp": timestamp, "clientToken": "token", "version": version }

/delta 响应状态文档

{ "state": { "attribute1": integer2, "attribute2": "string2", ... "attributeN": boolean2 }, "metadata": { "attribute1": { "timestamp": timestamp }, "attribute2": { "timestamp": timestamp }, ... "attributeN": { "timestamp": timestamp } }, "timestamp": timestamp, "clientToken": "token", "version": version }

/documents 响应状态文档

{ "previous" : { "state": { "desired": { "attribute1": integer2, "attribute2": "string2", ... "attributeN": boolean2 }, "reported": { "attribute1": integer1, "attribute2": "string1", ... "attributeN": boolean1 } }, "metadata": { "desired": { "attribute1": { "timestamp": timestamp }, "attribute2": { "timestamp": timestamp }, ... "attributeN": { "timestamp": timestamp } }, "reported": { "attribute1": { "timestamp": timestamp }, "attribute2": { "timestamp": timestamp }, ... "attributeN": { "timestamp": timestamp } } }, "version": version-1 }, "current": { "state": { "desired": { "attribute1": integer2, "attribute2": "string2", ... "attributeN": boolean2 }, "reported": { "attribute1": integer2, "attribute2": "string2", ... "attributeN": boolean2 } }, "metadata": { "desired": { "attribute1": { "timestamp": timestamp }, "attribute2": { "timestamp": timestamp }, ... "attributeN": { "timestamp": timestamp } }, "reported": { "attribute1": { "timestamp": timestamp }, "attribute2": { "timestamp": timestamp }, ... "attributeN": { "timestamp": timestamp } } }, "version": version }, "timestamp": timestamp, "clientToken": "token" }

响应状态文档属性

  • previous - 成功更新后,包含对象在更新之前的 state。

  • current - 成功更新后,包含对象在更新之后的 state。

  • state

    • reported - 只有在事物报告了 reported 部分中的任何数据时才存在,并且仅包含请求状态文档中的字段。

    • desired - 只有在设备报告了 desired 部分中的任何数据时才存在,并且仅包含请求状态文档中的字段。

  • metadata - 包含 desired 和 reported 部分中每个属性的时间戳,因此,您可以确定状态的更新时间。

  • timestamp— 生成响应的 Epoch 日期和时间。 AWS IoT

  • clientToken - 只有在向 /update 主题发布有效 JSON 时使用了客户端令牌时才存在。

  • version - AWS IoT中共享的设备影子文档的当前版本。它将在文档先前版本号的基础上增加一个数。

错误响应文档

错误响应文档具有以下格式:

{ "code": error-code, "message": "error-message", "timestamp": timestamp, "clientToken": "token" }
  • code - 用于表明错误类型的 HTTP 响应代码。

  • message - 用于提供额外信息的文本消息。

  • timestamp— 生成响应的日期和时间 AWS IoT。此属性并非在所有错误响应文档中都存在。

  • clientToken - 只有在发布的消息中使用了客户端令牌时才存在。

有关更多信息,请参阅 Device Shadow 错误消息。

影子名称列表响应文档

影子名称列表响应文档具有以下格式:

{ "results": [ "shadowName-1", "shadowName-2", "shadowName-3", "shadowName-n" ], "nextToken": "nextToken", "timestamp": timestamp }
  • results - 影子名称数组。

  • nextToken - 在获取序列中的下一页的分页请求中使用的令牌值。在没有其它要返回的影子名称时,该属性不存在。

  • timestamp— 生成响应的日期和时间 AWS IoT。

文档属性

设备的影子文档具有以下属性:

state
desired

设备的所需状态。应用程序可以写入到文档的该部分以直接更新设备的状态,而无需连接到设备。

reported

设备的报告状态。设备写入到文档的该部分以报告其新状态。应用程序读取文档的该部分以确定设备的上次报告状态。

metadata

有关存储在文档 state 部分的数据的信息。其中包括 state 部分中每个属性的时间戳(以 Epoch 时间表示),让您能够确定它们的更新时间。

注意

元数据不会影响服务限制或定价的文档大小。有关更多信息,请参阅 AWS IoT Service Limits。

timestamp

表示消息何时发送 AWS IoT。通过使用消息中的时间戳以及 desired 或 reported 部分中各个属性的时间戳,设备可以确定属性的存在时间,即使设备没有内部时钟。

clientToken

特定于设备的字符串,让您能在 MQTT 环境中将响应与请求关联起来。

version

文档版本。文档每次更新时,此版本号都会递增。用于确保正在更新的文档为最新版本。

有关更多信息,请参阅 影子文档示例。

增量状态

增量状态是一种虚拟类型的状态,包含 desired 状态和 reported 状态之间的差异。对于 desired 部分中的字段,如果 reported 部分没有这些字段,则它们将包含在增量中。对于 reported 部分中的字段,如果 desired 部分没有这些字段,则它们不会包含在增量中。增量包含元数据,且其值与 desired 字段的元数据相同。例如:

{ "state": { "desired": { "color": "RED", "state": "STOP" }, "reported": { "color": "GREEN", "engine": "ON" }, "delta": { "color": "RED", "state": "STOP" } }, "metadata": { "desired": { "color": { "timestamp": 12345 }, "state": { "timestamp": 12345 } }, "reported": { "color": { "timestamp": 12345 }, "engine": { "timestamp": 12345 } }, "delta": { "color": { "timestamp": 12345 }, "state": { "timestamp": 12345 } } }, "version": 17, "timestamp": 123456789 } }

当嵌套对象不同时,增量将包含根路径。

{ "state": { "desired": { "lights": { "color": { "r": 255, "g": 255, "b": 255 } } }, "reported": { "lights": { "color": { "r": 255, "g": 0, "b": 255 } } }, "delta": { "lights": { "color": { "g": 255 } } } }, "version": 18, "timestamp": 123456789 }

Device Shadow 服务通过循环访问 desired 状态中的每个字段并将其与 reported 状态进行比较来计算增量。

数组的处理方式与值类似。如果 desired 部分中的数组与 reported 部分中的数组不匹配,则整个预期数组将被复制到增量中。

对影子文档进行版本控制

Device Shadow 服务支持在每个更新消息(请求和响应)中进行版本控制。这意味着,每次更新影子时,JSON 文档的版本将会增加。这可以确保两件事情:

  • 如果客户端尝试使用旧版本号覆盖影子,它将收到错误消息。客户端将被告知必须先进行重新同步,然后才能更新设备的影子。

  • 如果消息的版本比客户端存储的版本低,客户端则可决定不对该消息执行操作。

客户端可以在影子文档中不包含版本以绕过版本匹配。

影子文档中的客户端令牌

您可以将客户端令牌与 MQTT-based 消息一起使用,以验证请求和请求响应中是否包含相同的客户端令牌。这可以确保响应与请求相互关联。

注意

客户端令牌不能超过 64 字节。超过 64 字节的客户端令牌将导致 400(错误请求)响应和 Invalid clientToken(无效的客户端令牌)错误消息。

空影子文档属性

如果影子文档中的 reported 和 desired 属性不适用于当前影子状态,它们可能为空或省略。例如,只有在影子文档具有所需状态时,它才包含 desired 属性。以下是没有 desired 属性的状态文档的有效示例:

{ "reported" : { "temp": 55 } }

reported 属性也可能为空,例如,设备尚未更新影子时:

{ "desired" : { "color" : "RED" } }

如果更新导致 desired 或 reported 属性变为 null,则会将其从文档中删除。下面说明了如何将 desired 属性设置为 null 以删除该属性。例如,在设备更新其状态时,您可以执行该操作。

{ "state": { "reported": { "color": "red" }, "desired": null } }

影子文档也可能没有 desired 或 reported 属性,从而使影子文档为空。这是一个空影子(但有效)文档的示例。

{ }

影子文档中的数组值

影子支持数组,但将其视为正常值进行处理,因为对数组的更新将替换整个数组。无法更新数组的某个部分。

初始状态:

{ "desired" : { "colors" : ["RED", "GREEN", "BLUE" ] } }

更新:

{ "desired" : { "colors" : ["RED"] } }

最终状态:

{ "desired" : { "colors" : ["RED"] } }

数组不能包含空值。例如,以下数组无效并将被拒绝。

{ "desired" : { "colors" : [ null, "RED", "GREEN" ] } }