在设备中使用 Amazon IoT 基于 MQTT 的文件传输 - Amazon IoT Core
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 Amazon Web Services 服务入门

在设备中使用 Amazon IoT 基于 MQTT 的文件传输

要启动数据传输过程,设备必须接收初始数据集,其中至少包含一个流 ID。您可以通过在任务文档中包含初始数据集来使用 Jobs 计划设备的数据传输任务。当设备收到初始数据集时,它应该开始与 Amazon IoT 基于 MQTT 的文件传输进行交互。若要与 Amazon IoT 基于 MQTT 的文件传输交换数据,设备应:

您可以选择在初始数据集中包含流文件 ID 和流版本。将流文件 ID 发送到设备可以简化设备固件/软件的编程,因为设备无需发送 DescribeStream 请求来获取此 ID。设备可以在 GetStream 请求中指定流版本以强制执行一致性检查,以防流意外更新。

使用 DescribeStream 获取流数据

Amazon IoT 基于 MQTT 的文件传输提供 DescribeStream API 将流数据发送到设备。此 API 返回的流数据包括流 ID、流版本、流描述和流文件列表,每个流文件都有一个文件 ID 和文件大小信息(以字节为单位)。通过这些信息,设备可以选择任意文件来启动数据传输过程。

注意

如果您的设备在初始数据集中收到了所有必需的流文件 ID,则无需使用 DescribeStream API。

请按照以下步骤发送 DescribeStream 请求。

  1. 订阅“已接受”主题筛选条件 $aws/things/ThingName/streams/StreamId/description/json

  2. 订阅“已被拒绝”主题筛选条件 $aws/things/ThingName/streams/StreamId/rejected/json

  3. 发送消息到 $aws/things/ThingName/streams/StreamId/describe/json 以发布 DescribeStream 请求。

  4. 如果请求被接受,则您的设备会在“已接受”主题筛选条件中收到 DescribeStream 响应。

  5. 如果请求被拒绝,则您的设备会在“已被拒绝”主题筛选条件条件中收到的错误响应。

注意

如果您在显示的主题和主题筛选条件中将 json 替换为 cbor,则您的设备将收到 CBOR 格式的消息,该格式比 JSON 更紧凑。

DescribeStream 请求

使用 JSON 格式的典型 DescribeStream 请求类似于以下示例。

{ "c": "ec944cfb-1e3c-49ac-97de-9dc4aaad0039" }
  • (可选)“c”是客户端令牌字段。

    客户端令牌不能超过 64 字节。超过 64 字节的客户端令牌将导致错误响应和 InvalidRequest 错误消息。

DescribeStream 响应

使用 JSON 格式的 DescribeStream 响应类似于以下示例。

{ "c": "ec944cfb-1e3c-49ac-97de-9dc4aaad0039", "s": 1, "d": "This is the description of stream ABC.", "r": [ { "f": 0, "z": 131072 }, { "f": 1, "z": 51200 } ] }
  • c”是客户端令牌字段。如果它在 DescribeStream 请求中给出,则将会返回。使用客户端令牌将响应与其请求相关联。

  • s”是整数形式的流版本。您可以使用此版本对 GetStream 请求执行一致性检查。

  • r”包含流中的文件列表。

    • f”是整数形式的流文件 ID。

    • z”是以字节为单位的流文件大小。

  • d”包含流的描述。

从流文件中获取数据块

您可以使用 GetStream API,以便设备可以以小数据块的形式接收流文件,因此可以用于那些对处理大型数据块大小有限制的设备。要接收整个数据文件,设备可能需要发送或接收多个请求和响应,直到接收和处理了所有数据块。

GetStream 请求

请按照以下步骤发送 GetStream 请求。

  1. 订阅“已接受”主题筛选条件 $aws/things/ThingName/streams/StreamId/data/json

  2. 订阅“已被拒绝”主题筛选条件 $aws/things/ThingName/streams/StreamId/rejected/json

  3. 发布 GetStream 请求到主题 $aws/things/ThingName/streams/StreamId/get/json

  4. 如果请求被接受,您的设备将在“已接受”主题筛选条件下收到一个或多个 GetStream 响应。每个响应消息都包含单个数据块的基本信息和数据负载。

  5. 重复步骤 3 和 4 以接收所有数据块。如果请求的数据量大于 128 KB,则必须重复这些步骤。您必须对您的设备进行编程,以使用多个 GetStream 请求接收所有请求的数据。

  6. 如果请求被拒绝,您的设备将在“已被拒绝”主题筛选条件下收到错误响应。

注意
  • 如果您在显示的主题和主题筛选条件中将“json”替换为“cbor”,则您的设备将收到 CBOR 格式的消息,这种格式比 JSON 更紧凑。

  • Amazon IoT 基于 MQTT 的文件传输将数据块的大小限制为 128 KB。如果您对超过 128 KB 的数据块发出请求,请求将失败。

  • 您可以对总大小大于 128 KB 的多个数据块发出请求(例如,如果您请求 5 个数据块,每个各 32 KB,则共有 160 KB 的数据)。在这种情况下,请求不会失败,但您的设备必须发出多个请求才能接收请求的所有数据。当您的设备提出额外请求时,该服务将发送额外的数据块。我们建议您仅在正确接收和处理之前的响应之后才继续执行新的请求。

  • 无论请求的数据总大小如何,您都应该对设备进行编程,以便在未收到数据块或未正确接收数据块时启动重试。

使用 JSON 格式的典型 GetStream 请求类似于以下示例。

{ "c": "1bb8aaa1-5c18-4d21-80c2-0b44fee10380", "s": 1, "f": 0, "l": 4098, "o": 2, "n": 100, "b": "..." }
  • [可选]“c”是客户端令牌字段。

    客户端令牌不能超过 64 字节。超过 64 字节的客户端令牌将导致错误响应和 InvalidRequest 错误消息。

  • [可选]“s”是流版本字段(整数)。

    基于 MQTT 的文件传输应用基于此请求的版本和云中的最新流版本的一致性检查。如果从设备发送的 GetStream 请求中的流版本与云中的最新流版本不匹配,则服务会发送错误响应和 VersionMismatch 错误消息。通常,设备会在初始数据集或对 DescribeStream 的响应中接收预期(最新)的流版本。

  • f”是流文件 ID(范围为 0 到 255 的整数)。

    使用 Amazon CLI 或软件开发工具包创建或更新流时,需要流文件 ID。如果设备请求了 ID 不存在的流文件,则该服务将发送错误响应和 ResourceNotFound 错误消息。

  • l”是以字节为单位的数据块大小(范围为 256 到 131,072 的整数)。

    请参阅 为 GetStream 请求构建位图 以了解如何使用位图字段指定流文件的哪些部分将在 GetStream 响应中返回. 如果设备指定的数据块大小超出范围,则服务会发送错误响应和 BlockSizeOutOfBounds 错误消息。

  • [可选]“o”是流文件中数据块的偏移量(范围为 0 到 98,304 的整数)。

    请参阅 为 GetStream 请求构建位图 以了解如何使用位图字段指定流文件的哪些部分将在 GetStream 响应中返回. 最大值 98,304 是基于 24 MB 流文件大小限制和 256 字节的最小数据块大小计算得出的。如果未指定,默认值为 0。

  • [可选]“n”是请求的数据块数量(范围为 0 到 98,304 的整数)。

    “n”字段指定 (1) 请求的数据块数量,或 (2) 使用位图字段 (“b”) 时,位图请求将返回的数据块数量的限制。第二种用法是可选的。如果没有定义,则默认为 131072/DataBlockSize

  • [可选]“b”是一个位图,表示正在请求的数据块。

    使用位图,您的设备可以请求非连续的数据块,这使得处理错误后重试的操作更加方便。请参阅 为 GetStream 请求构建位图 了解如何使用位图字段指定流文件的哪一部分将在 GetStream 响应中返回。对于此字段,将位图转换为以十六进制表示法表示位图值的字符串。位图必须小于 12,288 个字节。

GetStream 响应

JSON 格式的 GetStream 响应对于每个请求的数据块而言均如此示例所示。

{ "c": "1bb8aaa1-5c18-4d21-80c2-0b44fee10380", "f": 0, "l": 4098, "i": 2, "p": "..." }
  • c”是客户端令牌字段。如果它在 GetStream 请求中给出,则将会返回。使用客户端令牌将响应与其请求相关联。

  • f”是当前数据块负载所属的流文件的 ID。

  • l”是数据块负载的大小(以字节为单位)。

  • i”是负载中包含的数据块的 ID。数据块从 0 开始编号。

  • p”包含数据块负载。此字段是一个字符串,用十六进制表示法表示数据块的值。

为 GetStream 请求构建位图

您可以使用 GetStream 请求中的位图字段 (b) 从流文件中获取非连续数据块。这有助于 RAM 容量有限的设备处理网络交付问题。设备只能请求那些未接收或未正确接收的数据块。位图确定将返回流文件的哪些数据块。对于位图中设置为 1 的每个位,将返回相应的流文件数据块。

下面的示例将演示如何在 GetStream 请中指定位图机器支持的字段。例如,您希望以 256 字节的数据块(块大小)接收流文件。将每个 256 字节的数据块视为有一个指定其在文件中位置的数字,从 0 开始。因此,数据块 0 是文件中第一个 256 字节的数据块,数据块 1 是第二个,依此类推。您想要从文件中请求数据块 20、21、24 和 43。

数据块偏移

由于第一个数据块是第 20 号,因此指定偏移量(字段 o)为 20,以节省位图中的空间。

数据块数量

为了确保您的设备收到的数据块数量不会超过其在有限内存资源中所能处理的数量,您可以指定基于 MQTT 的文件传输发送的每条消息中应返回的最大数据块数量。请注意,如果位图本身指定的数据块数量小于此数值,或者如果它会使基于 MQTT 的文件传输发送的响应消息总大小大于每个 GetStream 请求 128 KB 的服务限制,则将忽略此值。

数据块位图

位图本身是一个以十六进制表示法表示的无签名字节数组,并以数字字符串的形式包含在 GetStream 请求中。但要构造这个字符串,我们首先要将位图视为一个位的长序列(二进制数)。如果此序列中的位设置为 1,则流文件中的相应数据块将被发送回设备。在我们的示例中,我们希望接收数据块 20、21、24 和 43,因此我们必须在位图中设置位 20、21、24 和 43。我们可以使用数据块偏移来节省空间,因此在从每个数据块编号中减去偏移后,我们希望设置位 0、1、4 和 23,如下例所示。

1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1

一次取一个字节(8 位),这个字节通常被写作:“0b00010011”、“0b00000000”和“0b10000000”。位 0 显示在第一个字节末尾的二进制表示中,位 23 显示在最后一个字节的开头。除非您知道约定,否则这种表示方式可能会令人困惑不已。第一个字节包含位 7-0(按该顺序),第二个字节包含位 15-8,第三个字节包含位 23-16,依此类推。在十六进制表示法中,这将转换为“0x130080”。

提示

您可以将标准二进制转换为十六进制表示法。一次取四个二进制数字,并将它们转换为十六进制等效数字。例如,“0001”变为“1”,“0011”变成 “3”,依此类推。

将这一切结合起来,我们的 GetStream 请求在 JSON 格式中看起来与下方类似。

{ "c" : "1", // client token "s" : 1, // expected stream version "l" : 256, // block size "f" : 1, // source file index id "o" : 20, // block offset "n" : 32, // number of blocks "b" : "0x130080" // A missing blockId bitmap starting from the offset }

处理来自 Amazon IoT 基于 MQTT 的文件传输的错误

DescribeStreamGetStream API 发送到设备的错误响应包含客户端令牌、错误代码和错误消息。典型的错误响应类似于以下示例。

{ "o": "BlockSizeOutOfBounds", "m": "The block size is out of bounds", "c": "1bb8aaa1-5c18-4d21-80c2-0b44fee10380" }
  • 如果出现错误,则“o”为指示错误原因的代码。有关更多详细信息,请参阅本部分后面的错误代码。

  • m”是包含错误详细信息的错误消息。

  • c”是客户端令牌字段。如果它在 DescribeStream 请求中提供,则可能会返回。您可以使用客户端令牌将响应与其请求相关联。

    客户端令牌字段并不总是包含在错误响应中。当请求中给出的客户端令牌无效或格式不正确时,它不会在错误响应中返回。

注意

为了向后兼容,错误响应中的字段可能采用非缩写形式。例如,错误代码可能由“code”或“o”字段指定,客户端令牌字段可以由“clientToken”或“c”字段指定。建议您使用上面显示的缩写形式。

InvalidTopic

流消息的 MQTT 主题无效。

InvalidJson

流请求不是有效的 JSON 文档。

InvalidCbor

流请求不是有效的 CBOR 文档。

InvalidRequest

请求整体被标识为格式错误。有关更多信息,请参阅错误消息。

Unauthorized

请求未获授权访问存储介质(如 Amazon S3)中的流数据文件。有关更多信息,请参阅错误消息。

BlockSizeOutOfBounds

数据块大小超出了界限。请参阅 Amazon IoT Core Service Quotas中的“基于 MQTT 的文件传输”部分。

OffsetOutOfBounds

偏移超出界限。请参阅 Amazon IoT Core Service Quotas中的“基于 MQTT 的文件传输”部分。

BlockCountLimitExceeded

请求数据块的数量超出了界限。请参阅 Amazon IoT Core Service Quotas中的“基于 MQTT 的文件传输”部分。

BlockBitmapLimitExceeded

请求位图的大小超出了界限。请参阅 Amazon IoT Core Service Quotas中的“基于 MQTT 的文件传输”部分。

ResourceNotFound

找不到请求的流、文件、文件版本或数据块。有关更多详细信息,请参阅错误消息。

VersionMismatch

请求中的流版本与基于 MQTT 的文件传输功能中的流版本不匹配。这表示自设备最初接收流版本以来,流数据已被修改。

ETagMismatch

流中的 S3 ETag 与最新 S3 对象版本的 ETag 不匹配。

InternalError

基于 MQTT 的文件传输中发生内部错误。