你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

从 IoT 中心发送云到设备的消息

若要从解决方案后端向设备应用发送单向通知,可从 IoT 中心向设备发送云到设备的消息。 有关 Azure IoT 中心支持的其他云到设备选项的介绍,请参阅云到设备的通信指南

注意

本文所述的功能只能用于 IoT 中心的标准层。 有关 IoT 中心基本层和标准/免费层的详细信息,请参阅选择适合你的解决方案的 IoT 中心层

可以通过面向服务的终结点 /messages/devicebound 发送从云到设备的消息。 随后设备可以通过特定于设备的终结点 /devices/{deviceId}/messages/devicebound 接收这些消息。

要将每个从云到设备的消息都设为以单个设备为目标,请通过 IoT 中心将 to 属性设置为 /devices/{deviceId}/messages/devicebound

每个设备队列最多可以保留 50 条云到设备的消息。 如果你尝试向同一设备发送更多消息,则会发生错误。

云到设备的消息生命周期

为了保证至少一次消息传递,IoT 中心将云到设备的消息保留在每个设备队列中。 在 IoT 中心从队列中删除消息之前,设备必须显式确认消息的相关操作已完成。 此方法保证了连接失败和设备故障时能够恢复。

下图显示了生命周期状态图:

此图显示云到设备消息的生命周期状态图。

IoT 中心服务向设备发送消息时,该服务会将消息状态设置为“排队”。 当设备想要接收某条消息时,IoT 中心会通过将状态设置为“不可见”来锁定该消息。 这种状态使得设备上的其他线程可以开始接收其他消息。 当设备线程完成消息的处理后,会通过完成消息来通知 IoT 中心。 随后 IoT 中心会将状态设置为“已完成”

设备还可以:

  • 拒绝消息,这会使 IoT 中心将此消息设置为“死信”状态。 通过消息队列遥测传输 (MQTT) 协议进行连接的设备无法拒绝云到设备的消息。

  • 放弃消息,这会使 IoT 中心将消息放回队列,并将状态设置为“已排队”。 通过 MQTT 协议连接的设备无法放弃云到设备的消息。

线程可能无法处理消息,且不通知 IoT 中心。 在此情况下,在可见性超时(或锁定超时)之后,消息从不可见状态自动转换回已排队状态。 此超时的值为一分钟,无法更改。

消息可以在“已排队”与“不可见”状态之间转换的次数,以 IoT 中心上“最大传送计数”属性中指定的次数为上限。 在该转换次数之后,IoT 中心会将消息的状态设置为“死信”。 同样,IoT 中心也会在消息的到期时间之后,将消息的状态设置为“死信”。 有关详细信息,请参阅消息过期(生存时间)

如何使用 IoT 中心发送云到设备的消息一文介绍了如何从云端发送云到设备的消息以及如何在设备上接收这些消息。

通常只要丢失消息不影响应用程序逻辑,设备就会完成云到设备的消息。 举例来说,当设备已在本地保留消息内容或已成功执行某项操作时,设备必须显式确认消息的相关操作已完成,然后才能删除消息。 消息还可能携带暂时性信息,这类信息的丢失不会影响应用程序的功能。 有时,对于长时间运行的任务,可以:

  • 在设备将任务说明保留到本地存储后完成该云到设备的消息。

  • 在作业进度的不同阶段,可以使用一条或多条设备到云的消息通知解决方案后端。

消息到期时间(生存时间)

每条云到设备的消息都有过期时间。 可通过以下选项之一设置此时间:

  • 服务中的 ExpiryTimeUtc 属性
  • 使用了指定为 IoT 中心属性的默认生存时间的 IoT 中心

有关消息过期的详细信息,请参阅云到设备配置选项

利用消息到期时间并避免将消息发送到已断开连接的设备的常见方法是设置较短的生存时间值。 此方法可达到与维护设备连接状态一样的效果,而且更加有效。 请求消息确认时,IoT 中心将通知你哪些设备:

  • 可以接收消息。
  • 不处于联机状态,或出现故障。

消息反馈

发送云到设备的消息时,服务可以请求传送每条消息的反馈(关于该消息的最终状态)。 可以配置消息反馈,方法是:将要发送的设备到云消息中的 iothub-ack 应用程序属性设置为以下四个值之一:

Ack 属性值 行为
默认。 IoT 中心不生成反馈消息。
积极 如果云到设备的消息达到“已完成”状态,IoT 中心将生成反馈消息
消极 云到设备的消息达到“死信”状态时,IoT 中心生成反馈消息
full IoT 中心在任一情况下都会生成反馈消息。

如果 Ack 属性值已设置为 full,但未收到反馈消息,则意味着反馈消息已过期。 该服务无法了解原始消息的经历。 实际上,服务应该确保它可以在反馈过期之前对其进行处理。 最长过期时间是两天,因此当发生故障时,有时间让服务再次运行。

终结点中所述,IoT 中心通过面向服务的终结点 /messages/servicebound/feedback 以消息方式传送反馈。 接收反馈的语义与云到设备消息的语义相同。 可能的话,消息反馈将放入单个消息中,其格式如下:

属性 说明
EnqueuedTime 一个时间戳,指示中心收到反馈消息的时间。
UserId {iot hub name}
ContentType application/vnd.microsoft.iothub.feedback.json

批处理达到 64 条消息时,或距离上次发送时间已过去 15 秒时(以首先满足的条件为准),系统会发出反馈。

正文是记录的 JSON 序列化数组,每条记录具有以下属性:

属性 说明
enqueuedTimeUtc 一个时间戳,指示消息结果的出现时间。 例如,一个指示中心何时收到了反馈消息或原始消息何时已过期的时间戳。
originalMessageId 与此反馈信息相关的云到设备消息的 MessageId。
statusCode 必需的字符串,在 IoT 中心生成的反馈消息中使用:
Success
已过期
DeliveryCountExceeded
已拒绝
Purged
description StatusCode 的字符串值。
deviceId 与此反馈相关的云到设备消息的目标设备的 DeviceId。
deviceGenerationId 与此反馈相关的云到设备消息的目标设备的 DeviceGenerationId。

服务必须指定 MessageId,云到设备消息才能将其反馈与原始消息相关联。

以下代码示例演示了反馈消息的正文:

[
  {
    "originalMessageId": "0987654321",
    "enqueuedTimeUtc": "2015-07-28T16:24:48.789Z",
    "statusCode": "Success",
    "description": "Success",
    "deviceId": "123",
    "deviceGenerationId": "abcdefghijklmnopqrstuvwxyz"
  },
  {
    ...
  },
  ...
]

所删除设备的待处理反馈

删除设备时,也会删除任何待处理的反馈。 设备反馈是成批发送的。 在设备确认收到消息和准备下一个反馈批之间可能会出现一个狭窄的窗口,通常不到一秒。 如果在那个狭窄的窗口中删除了设备,则不会出现反馈。

可以通过等待一段时间让待处理的反馈在删除设备之前到达来解决此问题。 删除设备后,应认为相关消息反馈丢失。

云到设备的配置选项

每个 IoT 中心都针对云到设备的消息传送公开以下配置选项:

属性 说明 范围和默认值
defaultTtlAsIso8601 云到设备消息的默认 TTL ISO_8601 间隔最长为 2 天(最短 1 分钟);默认值:1 小时
maxDeliveryCount 每个设备队列的云到设备最大传送计数 1 到 100;默认值:10
feedback.ttlAsIso8601 服务绑定反馈消息的保留时间 ISO_8601 间隔最长为 2 天(最短 1 分钟);默认值:1 小时
feedback.maxDeliveryCount 反馈队列的最大传送计数 1 到 100;默认值:10
feedback.lockDurationAsIso8601 反馈队列的锁定持续时间 ISO_8601 间隔为 5 到300秒(至少 5 秒);默认值:60 秒。

可以通过以下方式之一来设置配置选项:

  • Azure 门户:在 IoT 中心的“中心设置”下,选择“内置终结点”,然后转到“云到设备的消息传递”。 (Azure 门户当前不支持设置 feedback.maxDeliveryCountfeedback.lockDurationAsIso8601 属性。)

在门户中为云到设备消息设置配置选项

  • Azure CLI:使用 az iot hub update 命令:

    az iot hub update --name {your IoT hub name} \
        --set properties.cloudToDevice.defaultTtlAsIso8601=PT1H0M0S
    
    az iot hub update --name {your IoT hub name} \
        --set properties.cloudToDevice.maxDeliveryCount=10
    
    az iot hub update --name {your IoT hub name} \
        --set properties.cloudToDevice.feedback.ttlAsIso8601=PT1H0M0S
    
    az iot hub update --name {your IoT hub name} \
        --set properties.cloudToDevice.feedback.maxDeliveryCount=10
    
    az iot hub update --name {your IoT hub name} \
        --set properties.cloudToDevice.feedback.lockDurationAsIso8601=PT0H1M0S
    

后续步骤

若要了解可用于接收云到设备消息的 SDK,请参阅 Azure IoT 中心 SDK

若要尝试接收云到设备的消息,请参阅发送云到设备教程。