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

IoT 应用程序到设备命令

Azure IoT 中心

应用程序使用两种主要机制将命令发送到 IoT 设备:云到设备的消息传送直接方法

  • 应用程序将云到设备的消息发送到 IoT 平台上特定于设备的消息队列,供设备在连接时读取。 设备决定何时读取消息。

  • 应用程序通过专用IoT设备终结点使用请求-响应模式直接在已连接设备上调用直接方法

本文讨论云到设备消息传递和直接方法的特征。 本文还介绍如何将直接方法与协议网关和连接的备用设备一同使用。

云到设备的消息传送

应用程序将特定设备的云到设备命令消息发送到 Azure IoT 中心,中心将消息存储在特定于设备的队列中。 IoT 中心将消息发送到特定于设备的队列,而不考虑设备是否已连接。

显示 IoT 中心如何将消息存储到每个设备的内部消息队列中以及轮询这些消息的设备的示意图。

使用云到设备的消息传送时,需要考虑以下注意事项:

  • 消息队列有效地充当设备的邮箱,设备负责在连接新消息时轮询其消息队列。
  • 设备以先进先出的方式接收消息,使云到设备的消息传送非常适合按顺序读取和操作消息。
  • 消息具有可配置的过期时间,因此最终可以从设备的消息队列中删除未读的消息。
  • 对于有状态通信,应用程序可以使用反馈接收方来监视消息传送和确认。 应用程序可以使用单个反馈接收方监视所有设备的所有消息队列。

直接方法

应用程序直接在连接的 IoT 设备上调用直接方法,并期望设备执行这些方法,并注册到 IoT 中心。 IoT 中心通过直接通道在连接的设备上调用直接方法,设备负责执行函数并返回即时结果。

此示意图显示 IoT 中心如何使用直接方法在单个设备上直接调用代码。

使用直接方法时需考虑下列事项:

  • 如果在方法完成之前 IoT 中心与设备之间的连接断开,直接方法将失败。 应用程序可以捕获和处理重新尝试命令的失败。
  • 由于没有队列,因此需要直接方法序列化的应用程序需要管理方法调用的顺序,因此完成上一个方法将调用下一个方法。
  • 调用直接方法允许应用程序设置两个超时。 一个超时指定 IoT 中心应在放弃之前等待设备连接多久,另一个超时指定调用方在放弃之前应等待方法完成并做出响应的等待时间。

具有协议网关的直接方法

使用协议网关的 IoT 应用程序可以从直接方法的连接强制和请求-响应模型中获益。 云网关或协议网关允许代表设备代理自定义协议通信,将预先存在的不同设备连接到 IoT 中心。 协议网关同样可以通过将方法序列化为与设备兼容的协议消息来抽象直接方法模型。

此示意图说明使用协议网关代理从设备到 IoT 中心的自定义协议通信的直接方法调用序列。

  1. 应用程序代表协议网关中的设备调用直接方法。
  2. 对于方法实现,网关将方法转换为特定于设备的协议,并将消息发送到设备。 设备不知道云实现的任何更改。
  3. 当设备完成消息并做出响应时,网关将特定于设备的状态转换为方法响应。
  4. IoT 中心通过填充调用方的方法结果来完成直接方法。

Azure 协议网关开源项目将直接方法本机转换为 MQTT 协议消息,易于扩展,并演示了其他协议适配器的此编程模型。

连接的备用设备

IoT 命令方案可能涉及处于低功率空闲状态(不处于活动状态)的已连接待机设备。 移动短信服务 (短信) 可以发送唤醒信号,将这些设备转换为完全正常运行状态。

此示意图说明通过 Azure IoT API 发送的短信消息或命令如何唤醒设备并将其连接到 IoT 中心来接收命令。

  1. 应用程序使用 ServiceClient API 将命令发送到设备ServiceClient 的一个实例可以发送消息并调用多个设备的方法。
  2. 应用程序还会通过移动提供商的 SMS 网关向备用设备发送短信唤醒呼叫。
  3. 唤醒时,备用设备使用 DeviceClient API 连接到 IoT 中心并接收命令。 DeviceClient 的一个实例表示连接到 IoT 中心的单个设备。

使用直接方法确定设备连接状态

通过 SMS 网关发送不必要的唤醒消息会非常昂贵。 在将实际命令发送到设备之前,请使用连接和方法超时来确定设备是否已连接,并在必要时发送唤醒。

    TimeSpan connTimeOut = FromSeconds(0); // Period to wait for device to connect.
    TimeSpan funcTimeOut = FromSeconds(30); // Period to wait for method to execute.

    while (true) {
        // Send the command via direct method. Initially use a timeout of zero
        // for the connection, which determines whether the device is connected to
        // IoT Hub or needs an SMS wakeup sent to it.

        var method = new CloudToDeviceMethod("RemoteCommand", funcTimeOut, connTimeOut);
        methodInvocation1.SetPayloadJson(CommandPayload);

        var response = await serviceClient.InvokeDeviceMethodAsync(deviceId, method);

        // [DeviceNotConnected] represents a return value from the CloudToDeviceMethod
        // method. That method is not implemented in this sample.
        if (response == [DeviceNotConnected] && connTimeOut == 0) {
            // The device is not currently connected and needs an SMS wakeup. This
            // device should wake up within a period of < 30 seconds. Send the wakeup
            // and retry the method request with a 30 second timeout on waiting for
            // the device to connect.

            connTimeOut = FromSeconds(30); // Set a 30 second connection timeout.
            SendAsyncSMSWakeUpToDevice(); // Send SMS wakeup through mobile gateway.
            continue; // Retry with new connection timeout.
        } else {
            // The method either succeeded or failed.
            ActOnMethodResult(var);
            break;
        }
    }

若要仅检查连接性,请使用连接超时为零的空方法实现简单的 ping。 例如:

var method = new CloudToDeviceMethod("Ping", 0, 0);

作者

本文由 Microsoft 维护, 它最初是由以下贡献者撰写的。

主要作者:

后续步骤