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

设备和任务

Device communication with jobs

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

  • MQTT

  • HTTP Signature 版本 4

  • HTTP TLS

Using the MQTT protocol

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

注意

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

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

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

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

利用此方法,您的设备可使用其特定于设备的证书和私有密钥向 Amazon 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 来获取和开始下一个待处理任务执行。

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

Using HTTP Signature Version 4

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

注意

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

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

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

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

利用这种通信方法,您的设备将使用 IAM 凭证向 Amazon 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

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

注意

在通过 HTTP TLS 与 Amazon 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

对设备进行编程以使用任务

本部分中的示例使用 MQTT 来演示设备如何使用 Amazon 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

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

设备工作流程

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

Option a: Get the next job
  1. 当设备首次联机时,它应订阅设备的 notify-next 主题。

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

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

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

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

  6. 通过使用此 jobId 调用 DescribeJobExecution MQTT API 来继续监控任务执行。如果删除了任务执行,DescribeJobExecution 将返回 ResourceNotFoundException

    如果在设备运行任务时取消或删除了任务执行,则设备应能够恢复到有效状态。

  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. (可选)您可在调用 stepTimeoutInMinutes 时为 UpdateJobExecution 设置值来添加步骤计时器。

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

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

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

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

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

开始新任务

New job notification

在创建新任务时,Amazon 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 information

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

More Information(2)

如果请求成功,Amazon 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 > } } }
注意

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

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

报告任务执行状态

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 状态。步骤计时器对您在创建任务时设置的进行中计时器没有任何影响。

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

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 属性可包含任意数量的名称-值对。

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

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

其他任务

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 }] } }

任务通知

当任务待处理或列表中的第一个任务执行更改时,Amazon 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 主题的更多信息,请参阅 设备通信协议

注意

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

Job pending

当某个事物的待处理任务执行列表中添加或删除了任务时,或者列表中的第一个任务执行更改时,Amazon 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 }