AWS IoT
开发人员指南
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

设备和作业

Device Communication with JobsUsing the MQTT ProtocolUsing HTTP Signature Version 4Using HTTP TLS
Device Communication with Jobs

设备可通过以下方法与 AWS IoT Jobs 服务进行通信:

  • MQTT

  • HTTP Signature 版本 4

  • HTTP TLS

Using the MQTT Protocol

AWS IoT Jobs 服务和设备之间的通信可通过 MQTT 协议进行。设备将订阅 MQTT 主题,以便获得新作业通知和接收来自 AWS IoT Jobs 服务的响应。设备在 MQTT 主题上发布以查询或更新作业执行的状态。每台设备都有自己的一般 MQTT 主题。有关发布和订阅 MQTT 主题的更多信息,请参阅 AWS IoT 的消息代理

注意

在通过 MQTT 与 AWS IoT Jobs 服务通信时,您必须使用正确的终端节点。使用 DescribeEndpoint 命令查找它。例如,如果您运行此命令:

aws iot describe-endpoint --endpoint-type iot:Data

您会获得与以下内容相似的结果:

{ "endpointAddress": "a1b2c3d4e5f6g7.iot.us-west-2.amazonaws.com" }

利用此方法,您的设备可使用其特定于设备的证书和私有密钥向 AWS IoT Jobs 服务进行身份验证。

设备可以:

  • 在待处理作业执行列表中添加或删除作业执行时收到通知,方法是订阅 $aws/things/thing-name/jobs/notify MQTT 主题,其中 thing-name 是与设备关联的事物的名称。

  • 在下一个待处理作业执行发生更改时收到通知,方式是通过订阅 $aws/things/thing-name/jobs/notify-next MQTT 主题,其中 thing-name 是与设备关联的事物的名称。

  • 通过调用 UpdateJobExecution API 来更新作业执行的状态。

  • 通过调用 DescribeJobExecution API 来查询作业执行的状态。

  • 通过调用 GetPendingJobExecutions API 来检索待处理作业执行的列表。

  • 通过使用 jobId DescribeJobExecution 调用 $next API 来检索下一个待处理作业执行。

  • 通过调用 StartNextPendingJobExecution API 来获取和开始下一个待处理作业执行。

AWS IoT Jobs 服务在 MQTT 主题上发布成功和失败消息。通过将 acceptedrejected 追加到用于发出请求的主题来构成该主题。例如,如果在 $aws/things/myThing/jobs/get 主题上发布请求消息,则 AWS IoT Jobs 服务将在 $aws/things/myThing/jobs/get/accepted 主题上发布成功消息,并在 $aws/things/myThing/jobs/get/rejected 主题上发布已拒绝消息。

Using HTTP Signature Version 4

AWS IoT Jobs 服务和设备之间的通信可通过端口 443 上的 HTTP Signature 版本 4 进行。这是由 AWS 开发工具包和 CLI 使用的方法。有关这些工具的更多信息,请参阅 AWS CLI 命令参考:iot-jobs-dataAWS 开发工具包和工具并参考您的首选语言的 IotJobsDataPlane 部分。

注意

在通过 HTTP Signature 版本 4 或使用 AWS 开发工具包或 CLI IotJobsDataPlane 命令与 AWS IoT Jobs 服务通信时,您必须使用正确的终端节点。使用 DescribeEndpoint 命令查找它。例如,如果您运行此命令:

aws iot describe-endpoint --endpoint-type iot:Jobs

您会获得与以下内容相似的结果:

{ "endpointAddress": "a1b2c3d4e5f6g7.jobs.iot.us-west-2.amazonaws.com" }

利用这种通信方法,您的设备将使用 IAM 凭证向 AWS IoT Jobs 服务进行身份验证。

可以使用此方法执行以下命令:

  • DescribeJobExecution

    aws iot-jobs-data describe-job-execution ...

  • GetPendingJobExecutions

    aws iot-jobs-data get-pending-job-executions ...

  • StartNextPendingJobExecution

    aws iot-jobs-data start-next-pending-job-execution ...

  • UpdateJobExecution

    aws iot-jobs-data update-job-execution ...

Using HTTP TLS

AWS IoT Jobs 服务和设备之间的通信可通过端口 8443 上的 HTTP TLS,使用支持此协议的第三方软件客户端进行。

注意

在通过 HTTP TLS 与 AWS IoT Jobs 服务通信时,您必须使用正确的终端节点。使用 DescribeEndpoint 命令查找它。例如,如果您运行此命令:

aws iot describe-endpoint --endpoint-type iot:Jobs

您会获得与以下内容相似的结果:

{ "endpointAddress": "a1b2c3d4e5f6g7.jobs.iot.us-west-2.amazonaws.com" }

利用此方法,您的设备可使用基于 X.509 证书的身份验证(例如,其特定于设备的证书和私有密钥)。

可以使用此方法执行以下命令:

  • DescribeJobExecution

  • GetPendingJobExecutions

  • StartNextPendingJobExecution

  • UpdateJobExecution

对设备进行编程以使用 Jobs

本节中的示例使用 MQTT 来演示设备如何使用 AWS IoT Jobs 服务。或者,您也可以使用对应的 API 或 CLI 命令。对于这些示例,我们假定一台名为 MyThing 的设备订阅以下 MQTT 主题:

  • $aws/things/MyThing/jobs/notify (或者 $aws/things/MyThing/jobs/notify-next)

  • $aws/things/MyThing/jobs/get/accepted

  • $aws/things/MyThing/jobs/get/rejected

  • $aws/things/MyThing/jobs/jobId/get/accepted

  • $aws/things/MyThing/jobs/jobId/get/rejected

如果您使用 AWS IoT 的代码签名,则设备代码必须验证代码文件的签名。该签名在作业文档中的 codesign 属性内。有关验证代码文件签名的更多信息,请参阅设备代理示例

设备工作流程

设备可通过两种方式处理要执行的作业。

Option A: Get the next jobOption B: Pick from available jobs
Option A: Get the next job
  1. 当设备首次联机时,它应订阅设备的 notify-next 主题。

  2. 使用 jobId $next 调用 DescribeJobExecution MQTT API 以获取下一个作业、其作业文档和其他详细信息,包括保存在 statusDetails 中的任何状态。如果作业文档具有代码文件签名,则您必须验证签名,然后才能继续处理作业请求。

  3. 调用 UpdateJobExecution MQTT API 以更新作业状态。或者,要在一个调用中将此步骤与上一步骤合并,设备可调用 StartNextPendingJobExecution

  4. (可选)您可在调用 UpdateJobExecutionStartNextPendingJobExecution 时为 stepTimeoutInMinutes 设置值来添加步骤计时器。

  5. 使用 UpdateJobExecution MQTT API 执行作业文档所指定的操作以报告作业的进度。

  6. 通过使用此 jobId 调用 DescribeJobExecution MQTT API 来继续监控作业执行。如果在设备运行作业时取消或删除了作业执行,则设备应能够恢复到有效状态。

  7. 在作业完成后调用 UpdateJobExecution MQTT API 以更新作业状态并报告成功或失败。

  8. 由于此作业的执行状态已更改为最终状态,因此,可用于执行的下一个作业(如果有)将发生更改。设备将收到下一个待处理作业执行已更改的通知。此时,设备将按照步骤 2 中所述继续操作。

如果设备保持联机状态,则它在完成作业或添加新的待处理作业执行时,将继续收到下一个待处理作业执行的通知,包括其作业执行数据。在发生此情况时,设备将按照步骤 2 中所述继续操作。

Option B: Pick from available jobs
  1. 当设备首次联机时,它应订阅事物的 notify 主题。

  2. 调用 GetPendingJobExecutions MQTT API 以获取待处理作业执行的列表。

  3. 如果列表包含一个或多个作业执行,请选取一个作业执行。

  4. 调用 DescribeJobExecution MQTT API 以获取作业文档和其他详细信息,包括保存在 statusDetails 中的任何状态。

  5. 调用 UpdateJobExecution MQTT API 以更新作业状态。如果在此命令中将 includeJobDocument 字段设置为 true,则设备可跳过上一个步骤并在此时检索作业文档。

  6. (可选)您可在调用 UpdateJobExecution 时为 stepTimeoutInMinutes 设置值来添加步骤计时器。

  7. 使用 UpdateJobExecution MQTT API 执行作业文档所指定的操作以报告作业的进度。

  8. 通过使用此 jobId 调用 DescribeJobExecution MQTT API 来继续监控作业执行。如果在设备运行作业时取消或删除了作业执行,则设备应能够恢复到有效状态。

  9. 在作业完成后调用 UpdateJobExecution MQTT API 以更新作业状态并报告成功或失败。

如果设备保持联机状态,则在一个新的待处理作业执行变为可用时,它将收到所有待处理作业执行的通知。在发生此情况时,设备可按照步骤 2 中所述继续操作。

如果设备无法执行作业,它将调用 UpdateJobExecution MQTT API 来将作业状态更新为 REJECTED

开始新作业

new job notificationMore Information(1)
new job notification

在创建新作业时,AWS IoT Jobs 服务将在 $aws/things/thing-name/jobs/notify 主题上为每个目标设备发布一条消息。

More Information(1)

消息包含以下信息:

{ "timestamp":1476214217017, "jobs":{ "QUEUED":[{ "jobId":"0001", "queuedAt":1476214216981, "lastUpdatedAt":1476214216981, "versionNumber" : 1 }] } }

在对作业执行进行排队时,设备将在 '$aws/things/thingName/jobs/notify' 主题上收到此消息。

get job informationMore Information(2)
get job information

要获取有关作业执行的更多信息,请调用 DescribeJobExecution MQTT API 并将 includeJobDocument 字段设置为 true(默认值)。

More Information(2)

如果请求成功,AWS IoT Jobs 服务将在 $aws/things/MyThing/jobs/0023/get/accepted 主题上发布消息:

{ "clientToken" : "client-001", "timestamp" : 1489097434407, "execution" : { "approximateSecondsBeforeTimedOut": number, "jobId" : "023", "status" : "QUEUED", "queuedAt" : 1489097374841, "lastUpdatedAt" : 1489097374841, "versionNumber" : 1, "jobDocument" : { < contents of job document > } } }

注意

如果请求失败,AWS IoT Jobs 服务将在 $aws/things/MyThing/jobs/0023/get/rejected 主题上发布消息。

设备现在已有作业文档,它可使用该文档执行作业的远程操作。如果作业文档包含一个 Amazon S3 预签名 URL,则设备可使用该 URL 下载作业的任何所需文件。

报告作业执行状态

Update Execution StatusMore Information (3)
Update Execution Status

当设备执行作业时,它可调用 UpdateJobExecution MQTT API 来更新作业执行的状态。

More Information (3)

例如,设备可通过在 IN_PROGRESS 主题上发布以下消息来将作业执行状态更新为 $aws/things/MyThing/jobs/0023/update

{ "status":"IN_PROGRESS", "statusDetails": { "progress":"50%" }, "expectedVersion":"1", "clientToken":"client001" }

Jobs 通过将消息发布到 $aws/things/MyThing/jobs/0023/update/accepted$aws/things/MyThing/jobs/0023/update/rejected 主题来做出响应:

{ "clientToken":"client001", "timestamp":1476289222841 }

设备可通过调用 StartNextPendingJobExecution 来合并两个以前的请求。这将获取并开始下一个待处理作业执行,并允许设备更新作业执行状态。此请求还在有待处理作业执行时返回作业文档。

如果作业中包含 TimeoutConfig,则进行中计时器将开始运行。在调用 UpdateJobExecution 时,您还可通过设置 stepTimeoutInMinutes 的值来为作业执行设置步骤计时器。步骤计时器仅应用于您更新的作业执行。您每次更新作业执行时,可以为此计时器设置新值。您还可在调用 StartNextPendingJobExecution 时创建步骤计时器。如果作业执行保持在 IN_PROGRESS 状态的时间长度超过了此步骤计时器间隔,它将失败,并切换为最终 TIMED_OUT 状态。步骤计时器对您在创建作业时设置的进行中计时器没有任何影响。

注意

作业超时功能目前在 AWS GovCloud(美国)区域中不可用。

status 字段可设置为 IN_PROGRESSSUCCEEDEDFAILED。您无法更新已处于最终状态的作业执行的状态。

Report Execution CompletedMore Information(4)
Report Execution Completed

在设备执行完作业后,它将调用 UpdateJobExecution MQTT API。如果作业已成功,则将 status 设置为 SUCCEEDED,并在消息负载的 statusDetails 中,将有关作业的其他信息作为名称-值对添加。作业执行完成时,进行中计时器和步骤计时器结束。

More Information(4)

例如:

{ "status":"SUCCEEDED", "statusDetails": { "progress":"100%" }, "expectedVersion":"2", "clientToken":"client-001" }

如果作业未成功,则将 status 设置为 FAILED,并在 statusDetails 中,添加有关出现的错误的信息:

{ "status":"FAILED", "statusDetails": { "errorCode":"101", "errorMsg":"Unable to install update" }, "expectedVersion":"2", "clientToken":"client-001" }

注意

statusDetails 属性可包含任意数量的名称-值对。

在 AWS IoT Jobs 服务收到此更新时,它会在 $aws/things/MyThing/jobs/notify 主题上发布消息以指示作业执行已完成:

{ "timestamp":1476290692776, "jobs":{} }

其他作业

additional jobsMore Information(5)
additional jobs

如果设备有其他待处理的作业执行,这些作业执行将包含在发布到 $aws/things/MyThing/jobs/notify 的消息中。

More Information(5)

例如:

{ "timestamp":1476290692776, "jobs":{ "QUEUED":[{ "jobId":"0002", "queuedAt":1476290646230, "lastUpdatedAt":1476290646230 }], "IN_PROGRESS":[{ "jobId":"0003", "queuedAt":1476290646230, "lastUpdatedAt":1476290646230 }] } }

作业通知

当作业待处理或列表中的第一个作业执行更改时,AWS IoT Jobs 服务将向保留主题发布 MQTT 消息。设备可通过订阅这些主题来跟踪待处理作业。

作业通知将作为 JSON 负载发布到 MQTT 主题。通知有两种:

  • ListNotification 包含一个列表,其中待处理的作业执行不超过 10 个。此列表中作业执行的状态值为 IN_PROGRESSQUEUED。它们依次按照状态(IN_PROGRESS 作业执行在 QUEUED 作业执行之前)和排队的时间进行排序。

    如果满足以下条件之一,则发布 ListNotification

    • 新的作业执行已排队或更改为非最终状态(IN_PROGRESSQUEUED)。

    • 旧的作业执行更改为最终状态(FAILEDSUCCEEDEDCANCELEDTIMED_OUTREJECTEDREMOVED)。

  • NextNotification 包含队列中下一个作业执行的摘要信息。

    每当列表中第一个作业执行更改时,则会发布 NextNotification

    • 新的作业执行作为 QUEUED 被添加到列表,并且在列表中排在第一。

    • 不是列表第一的现有作业执行的状态从 QUEUED 更改为 IN_PROGRESS,然后成为列表中的第一个。(当列表中没有其他 IN_PROGRESS 作业执行时,或者当状态从 QUEUED 更改为 IN_PROGRESS 的作业执行排队的时间早于列表中其他所有 IN_PROGRESS 作业执行时,会出现这种情况。)

    • 列表第一的作业执行状态更改为最终状态,并且从列表中删除。

有关发布和订阅 MQTT 主题的更多信息,请参阅 AWS IoT 的消息代理

注意

当您使用 HTTP Signature 版本 4 或 HTTP TLS 与 Jobs 通信时,通知不可用。

job pendingMore Information(6)
job pending

当某个事物的待处理作业执行列表中添加或删除了作业时,或者列表中的第一个作业执行更改时,AWS IoT Jobs 服务会在 MQTT 主题上发布消息:

  • $aws/things/thingName/jobs/notify

  • $aws/things/thingName/jobs/notify-next

More Information(6)

消息包含以下示例负载:

$aws/things/thingName/jobs/notify

{ "timestamp" : 10011, "jobs" : { "IN_PROGRESS" : [ { "jobId" : "other-job", "queuedAt" : 10003, "lastUpdatedAt" : 10009, "executionNumber" : 1, "versionNumber" : 1 } ], "QUEUED" : [ { "jobId" : "this-job", "queuedAt" : 10011, "lastUpdatedAt" : 10011, "executionNumber" : 1, "versionNumber" : 0 } ] } }

$aws/things/thingName/jobs/notify-next

{ "timestamp" : 10011, "execution" : { "jobId" : "other-job", "status" : "IN_PROGRESS", "queuedAt" : 10009, "lastUpdatedAt" : 10009, "versionNumber" : 1, "executionNumber" : 1, "jobDocument" : {"c":"d"} } }

可能的作业执行状态值为 QUEUEDIN_PROGRESSFAILEDSUCCEEDEDCANCELEDTIMED_OUTREJECTEDREMOVED

以下一系列示例显示了,在创建作业执行和作业执行从一种状态更改为另一种状态时向每个主题发布的通知。

首先,创建了一个名为 job1 的作业。此通知发布到 jobs/notify 主题:

{ "timestamp": 1517016948, "jobs": { "QUEUED": [ { "jobId": "job1", "queuedAt": 1517016947, "lastUpdatedAt": 1517016947, "executionNumber": 1, "versionNumber": 1 } ] } }

此通知发布到 jobs/notify-next 主题:

{ "timestamp": 1517016948, "execution": { "jobId": "job1", "status": "QUEUED", "queuedAt": 1517016947, "lastUpdatedAt": 1517016947, "versionNumber": 1, "executionNumber": 1, "jobDocument": { "operation": "test" } } }

当创建另一个作业 (job2) 时,此通知将发布到 jobs/notify 主题:

{ "timestamp": 1517017192, "jobs": { "QUEUED": [ { "jobId": "job1", "queuedAt": 1517016947, "lastUpdatedAt": 1517016947, "executionNumber": 1, "versionNumber": 1 }, { "jobId": "job2", "queuedAt": 1517017191, "lastUpdatedAt": 1517017191, "executionNumber": 1, "versionNumber": 1 } ] } }

通知未发布到 jobs/notify-next 主题,因为队列中的下一个作业 (job1) 尚未更改。当 job1 开始执行时,其状态更改为 IN_PROGRESS。没有发布任何通知,因为作业列表和队列中的下一个作业尚未更改。

当添加第三个作业 (job3) 时,此通知将发布到 jobs/notify 主题:

{ "timestamp": 1517017906, "jobs": { "IN_PROGRESS": [ { "jobId": "job1", "queuedAt": 1517016947, "lastUpdatedAt": 1517017472, "startedAt": 1517017472, "executionNumber": 1, "versionNumber": 2 } ], "QUEUED": [ { "jobId": "job2", "queuedAt": 1517017191, "lastUpdatedAt": 1517017191, "executionNumber": 1, "versionNumber": 1 }, { "jobId": "job3", "queuedAt": 1517017905, "lastUpdatedAt": 1517017905, "executionNumber": 1, "versionNumber": 1 } ] } }

通知未发布到 jobs/notify-next 主题,因为队列中的下一个作业仍为 job1

job1 完成后,其状态更改为 SUCCEEDED,此通知将发布到 jobs/notify 主题:

{ "timestamp": 1517186269, "jobs": { "QUEUED": [ { "jobId": "job2", "queuedAt": 1517017191, "lastUpdatedAt": 1517017191, "executionNumber": 1, "versionNumber": 1 }, { "jobId": "job3", "queuedAt": 1517017905, "lastUpdatedAt": 1517017905, "executionNumber": 1, "versionNumber": 1 } ] } }

此时,已从队列中删除 job1,要执行的下一个作业是 job2。此通知发布到 jobs/notify-next 主题:

{ "timestamp": 1517186269, "execution": { "jobId": "job2", "status": "QUEUED", "queuedAt": 1517017191, "lastUpdatedAt": 1517017191, "versionNumber": 1, "executionNumber": 1, "jobDocument": { "operation": "test" } } }

如果 job3 必须在 job2 之前开始执行(不推荐),job3 的状态可以更改为 IN_PROGRESS。更改后,job2 则不再是队列中的下一个作业,此通知将发布到 jobs/notify-next 主题:

{ "timestamp": 1517186779, "execution": { "jobId": "job3", "status": "IN_PROGRESS", "queuedAt": 1517017905, "startedAt": 1517186779, "lastUpdatedAt": 1517186779, "versionNumber": 2, "executionNumber": 1, "jobDocument": { "operation": "test" } } }

没有向 jobs/notify 主题发布任何通知,因为没有添加或删除任何作业。

如果设备拒绝 job2,并且将其状态更新为 REJECTED,则此通知将发布到 jobs/notify 主题:

{ "timestamp": 1517189392, "jobs": { "IN_PROGRESS": [ { "jobId": "job3", "queuedAt": 1517017905, "lastUpdatedAt": 1517186779, "startedAt": 1517186779, "executionNumber": 1, "versionNumber": 2 } ] } }

如果 job3(仍在进行)被强制删除,则此通知将发布到 jobs/notify 主题:

{ "timestamp": 1517189551, "jobs": {} }

此时队列为空。此通知发布到 jobs/notify-next 主题:

{ "timestamp": 1517189551 }