从 IoT 中心发送云到设备的消息Send cloud-to-device messages from an IoT hub

若要从解决方案后端向设备应用发送单向通知,可从 IoT 中心向设备发送云到设备的消息。To send one-way notifications to a device app from your solution back end, send cloud-to-device messages from your IoT hub to your device. 有关 Azure IoT 中心支持的其他云到设备选项的介绍,请参阅云到设备的通信指南For a discussion of other cloud-to-device options supported by Azure IoT Hub, see Cloud-to-device communications guidance.

Note

本文介绍的功能仅在 IoT 中心的标准层中可用。The features described in this article are available only in the standard tier of IoT Hub. 有关基本和标准/免费 IoT 中心层的详细信息,请参阅选择合适的 IoT 中心层For more information about the basic and standard/free IoT Hub tiers, see Choose the right IoT Hub tier.

可以通过面向服务的终结点 /messages/devicebound 发送从云到设备的消息。You send cloud-to-device messages through a service-facing endpoint, /messages/devicebound. 随后设备可以通过特定于设备的终结点 /devices/{deviceId}/messages/devicebound 接收这些消息。A device then receives the messages through a device-specific endpoint, /devices/{deviceId}/messages/devicebound.

要将每个从云到设备的消息都设为以单个设备为目标,请通过 IoT 中心将 to 属性设置为 /devices/{deviceId}/messages/deviceboundTo target each cloud-to-device message at a single device, your IoT hub sets the to property to /devices/{deviceId}/messages/devicebound.

每个设备队列最多可以保留 50 条云到设备的消息。Each device queue holds, at most, 50 cloud-to-device messages. 尝试将更多消息传送到同一设备会导致错误。To try to send more messages to the same device results in an error.

云到设备的消息生命周期The cloud-to-device message lifecycle

为了保证至少一次消息传递,IoT 中心将云到设备的消息保留在每个设备队列中。To guarantee at-least-once message delivery, your IoT hub persists cloud-to-device messages in per-device queues. 设备必须显式确认完成,IoT 中心才会从队列中删除消息 。For the IoT hub to remove the messages from the queue, the devices must explicitly acknowledge completion. 这种方法可以保证连接失败和设备故障时能够复原。This approach guarantees resiliency against connectivity and device failures.

下图显示了生命周期状态图:The life-cycle state graph is displayed in the following diagram:

云到设备的消息生命周期

IoT 中心服务向设备发送消息时,该服务会将消息状态设置为“排队” 。When the IoT hub service sends a message to a device, the service sets the message state to Enqueued. 当设备想要接收某条消息时,IoT 中心会通过将状态设置为“不可见”来锁定该消息。 When a device wants to receive a message, the IoT hub locks the message by setting the state to Invisible. 这种状态使得设备上的其他线程可以开始接收其他消息。This state allows other threads on the device to start receiving other messages. 当设备线程完成消息的处理后,会通过完成消息来通知 IoT 中心 。When a device thread completes the processing of a message, it notifies the IoT hub by completing the message. 随后 IoT 中心会将状态设置为“已完成” 。The IoT hub then sets the state to Completed.

设备还可以:A device can also:

  • 拒绝 消息,这会使 IoT 中心将此消息设置为“死信”状态 。Reject the message, which causes the IoT hub to set it to the Dead lettered state. 通过消息队列遥测传输 (MQTT) 协议进行连接的设备无法拒绝云到设备的消息。Devices that connect over the Message Queuing Telemetry Transport (MQTT) Protocol can't reject cloud-to-device messages.

  • 放弃消息,这会使 IoT 中心将消息放回队列,并将状态设置为“已排队” 。Abandon the message, which causes the IoT hub to put the message back in the queue, with the state set to Enqueued. 通过 MQTT 协议连接的设备无法放弃云到设备的消息。Devices that connect over the MQTT Protocol can't abandon cloud-to-device messages.

线程可能无法处理消息,且不通知 IoT 中心。A thread could fail to process a message without notifying the IoT hub. 在此情况下,在可见性超时(或锁定超时)之后,消息从不可见状态自动转换回已排队状态 。In this case, messages automatically transition from the Invisible state back to the Enqueued state after a visibility time-out (or lock time-out). 此超时的值为一分钟,无法更改。The value of this time-out is one minute and cannot be changed.

消息可以在“已排队”与“不可见”状态之间转换的次数,以 IoT 中心上“最大传送计数”属性中指定的次数为上限 。The max delivery count property on the IoT hub determines the maximum number of times a message can transition between the Enqueued and Invisible states. 在该转换次数之后,IoT 中心会将消息的状态设置为“死信” 。After that number of transitions, the IoT hub sets the state of the message to Dead lettered. 同样,IoT 中心也会在消息的到期时间之后,将消息的状态设置为“死信” 。Similarly, the IoT hub sets the state of a message to Dead lettered after its expiration time. 有关详细信息,请参阅生存时间For more information, see Time to live.

如何使用 IoT 中心发送云到设备的消息一文介绍了如何从云端发送云到设备的消息以及如何在设备上接收这些消息。The How to send cloud-to-device messages with IoT Hub article shows you how to send cloud-to-device messages from the cloud and receive them on a device.

通常只要丢失消息不影响应用程序逻辑,设备就会完成云到设备的消息。A device ordinarily completes a cloud-to-device message when the loss of the message doesn't affect the application logic. 例如,设备已在本地保留消息内容或已成功执行操作。An example of this might be when the device has persisted the message content locally or has successfully executed an operation. 消息还可能携带暂时性信息,这类信息的丢失不会影响应用程序的功能。The message could also carry transient information, whose loss wouldn't impact the functionality of the application. 有时,对于长时间运行的任务,可以:Sometimes, for long-running tasks, you can:

  • 在设备将任务说明保留到本地存储后完成该云到设备的消息。Complete the cloud-to-device message after the device has persisted the task description in local storage.
  • 在作业进度的不同阶段,可以使用一条或多条设备到云的消息通知解决方案后端。Notify the solution back end with one or more device-to-cloud messages at various stages of progress of the task.

消息到期时间(生存时间)Message expiration (time to live)

每条云到设备的消息都有过期时间。Every cloud-to-device message has an expiration time. 可通过以下任一方式设置此时间:This time is set by either of the following:

  • 服务中的 ExpiryTimeUtc 属性The ExpiryTimeUtc property in the service
  • 使用了指定为 IoT 中心属性的默认生存时间的 IoT 中心 。The IoT hub, by using the default time to live that's specified as an IoT hub property

请参阅云到设备的配置选项See Cloud-to-device configuration options.

利用消息到期时间并避免将消息发送到已断开连接的设备的常见方法是设置较短的生存时间值 。A common way to take advantage of a message expiration and to avoid sending messages to disconnected devices is to set short time to live values. 此方法可达到与维护设备连接状态一样的效果,而且更加有效。This approach achieves the same result as maintaining the device connection state, but it is more efficient. 请求消息确认时,IoT 中心将通知你哪些设备:When you request message acknowledgments, the IoT hub notifies you which devices are:

  • 可以接收消息。Able to receive messages.
  • 不处于联机状态,或出现故障。Are not online or have failed.

消息反馈Message feedback

发送云到设备的消息时,服务可以请求传送每条消息的反馈(关于该消息的最终状态)。When you send a cloud-to-device message, the service can request the delivery of per-message feedback about the final state of that message. 为此,可将要发送的设备到云消息中的 iothub-ack 应用程序属性设置为以下四个值之一:You do this by setting the iothub-ack application property in the cloud-to-device message that's being sent to one of the following four values:

Ack 属性值Ack property value 行为Behavior
none IoT 中心不生成反馈消息(默认行为)。The IoT hub doesn't generate a feedback message (default behavior).
积极positive 如果云到设备的消息达到“已完成”状态,IoT 中心将生成反馈消息 。If the cloud-to-device message reaches the Completed state, the IoT hub generates a feedback message.
negativenegative 云到设备的消息达到“死信”状态时,IoT 中心生成反馈消息 。If the cloud-to-device message reaches the Dead lettered state, the IoT hub generates a feedback message.
fullfull IoT 中心在任一情况下都会生成反馈消息。The IoT hub generates a feedback message in either case.

如果 Ack 值为 full,且未收到反馈消息,则意味着反馈消息已过期。If the Ack value is full, and you don't receive a feedback message, it means that the feedback message has expired. 该服务无法了解原始消息的经历。The service can't know what happened to the original message. 实际上,服务应该确保它可以在反馈过期之前对其进行处理。In practice, a service should ensure that it can process the feedback before it expires. 最长过期时间是两天,因此当发生故障时,有时间让服务再次运行。The maximum expiration time is two days, which leaves time to get the service running again if a failure occurs.

终结点中所述,IoT 中心通过面向服务的终结点 /messages/servicebound/feedback 以消息方式传送反馈。As explained in Endpoints, the IoT hub delivers feedback through a service-facing endpoint, /messages/servicebound/feedback, as messages. 接收反馈的语义与云到设备消息的语义相同。The semantics for receiving feedback are the same as for cloud-to-device messages. 可能的话,消息反馈将放入单个消息中,其格式如下:Whenever possible, message feedback is batched in a single message, with the following format:

属性Property 说明Description
EnqueuedTimeEnqueuedTime 一个时间戳,指示中心收到反馈消息的时间A timestamp that indicates when the feedback message was received by the hub
UserIdUserId {iot hub name}
ContentTypeContentType application/vnd.microsoft.iothub.feedback.json

正文是记录的 JSON 序列化数组,每条记录具有以下属性:The body is a JSON-serialized array of records, each with the following properties:

属性Property 说明Description
EnqueuedTimeUtcEnqueuedTimeUtc 一个时间戳,指示消息的结果(例如,中心已收到反馈消息,或原始消息已过期)A timestamp that indicates when the outcome of the message happened (for example, the hub received the feedback message or the original message expired)
OriginalMessageIdOriginalMessageId 与此反馈信息相关的从云到设备的消息的 MessageIdThe MessageId of the cloud-to-device message to which this feedback information relates
StatusCodeStatusCode 必需的字符串,在 IoT 中心生成的反馈消息中使用:A required string, used in feedback messages that are generated by the IoT hub:
SuccessSuccess
ExpiredExpired
DeliveryCountExceededDeliveryCountExceeded
RejectedRejected
PurgedPurged
说明Description StatusCode 的字符串值String values for StatusCode
DeviceIdDeviceId 与此反馈信息相关的从云到设备的消息的目标设备的 DeviceIdThe DeviceId of the target device of the cloud-to-device message to which this piece of feedback relates
DeviceGenerationIdDeviceGenerationId 与此反馈信息相关的从云到设备的消息的目标设备的 DeviceGenerationIdThe DeviceGenerationId of the target device of the cloud-to-device message to which this piece of feedback relates

服务必须指定 MessageId ,云到设备的消息才能将其反馈与原始消息相关联。For the cloud-to-device message to correlate its feedback with the original message, the service must specify a MessageId.

以下代码演示了反馈消息的正文:The body of a feedback message is shown in the following code:

[
  {
    "OriginalMessageId": "0987654321",
    "EnqueuedTimeUtc": "2015-07-28T16:24:48.789Z",
    "StatusCode": 0,
    "Description": "Success",
    "DeviceId": "123",
    "DeviceGenerationId": "abcdefghijklmnopqrstuvwxyz"
  },
  {
    ...
  },
  ...
]

所删除设备的待处理反馈Pending feedback for deleted devices

删除设备时,也会删除任何待处理的反馈。When a device is deleted, any pending feedback is deleted as well. 设备反馈是成批发送的。Device feedback is sent in batches. 如果在设备确认收到消息和准备下一个反馈批次之间的窄窗口(通常少于 1 秒)内删除设备,则不会发生反馈。If a device is deleted in the narrow window (often less than 1 second) between when the device confirms receipt of the message and when the next feedback batch is prepared, the feedback will not occur.

可以通过等待一段时间让待处理的反馈在删除设备之前到达来解决此问题。You can address this behavior by waiting a period of time for pending feedback to arrive before deleting your device. 删除设备后,应认为相关消息反馈丢失。Related message feedback should be assumed lost once a device is deleted.

云到设备的配置选项Cloud-to-device configuration options

每个 IoT 中心都针对云到设备的消息传送公开以下配置选项:Each IoT hub exposes the following configuration options for cloud-to-device messaging:

属性Property 说明Description 范围和默认值Range and default
defaultTtlAsIso8601defaultTtlAsIso8601 云到设备消息的默认 TTLDefault TTL for cloud-to-device messages ISO_8601 间隔,最大为 2 天(最小为 1 分钟);默认值:1 小时ISO_8601 interval up to 2 days (minimum 1 minute); default: 1 hour
maxDeliveryCountmaxDeliveryCount 每个设备队列的云到设备最大传送计数Maximum delivery count for cloud-to-device per-device queues 1 到 100;默认值:10 个1 to 100; default: 10
feedback.ttlAsIso8601feedback.ttlAsIso8601 服务绑定反馈消息的保留时间Retention for service-bound feedback messages ISO_8601 间隔,最大为 2 天(最小为 1 分钟);默认值:1 小时ISO_8601 interval up to 2 days (minimum 1 minute); default: 1 hour
feedback.maxDeliveryCountfeedback.maxDeliveryCount 反馈队列的最大传送计数Maximum delivery count for the feedback queue 1 到 100;默认值:10 个1 to 100; default: 10
feedback.lockDurationAsIso8601feedback.lockDurationAsIso8601 反馈队列的最大传送计数Maximum delivery count for the feedback queue ISO_8601 间隔(5 到 300 秒,最小值 5 秒);默认值:60 秒。ISO_8601 interval from 5 to 300 seconds (minimum 5 seconds); default: 60 seconds.

可以通过以下方式之一来设置配置选项:You can set the configuration options in one of the following ways:

  • Azure 门户:在 IoT 中心的“设置” 下,选择“内置终结点” ,然后展开“云到设备消息” 。Azure portal: Under Settings on your IoT hub, select Built-in endpoints and expand Cloud to device messaging. (Azure 门户当前不支持设置 feedback.maxDeliveryCountfeedback.lockDurationAsIso8601 属性。)(Setting the feedback.maxDeliveryCount and feedback.lockDurationAsIso8601 properties is not currently supported in Azure portal.)

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

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

    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
    

后续步骤Next steps

有关可用于接收云到设备消息的 SDK 的信息,请参阅 Azure IoT SDKFor information about the SDKs that you can use to receive cloud-to-device messages, see Azure IoT SDKs.

若要尝试接收云到设备消息,请参阅发送云到设备教程。To try out receiving cloud-to-device messages, see the Send cloud-to-device tutorial.