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 命令案例可能牽涉到連線的待命裝置,這些裝置在未啟用時會處於低功耗的閒置狀態。 行動短訊息服務 (SMS) 這類機制可以傳送喚醒訊號,將這些裝置轉換為完全可操作的狀態。

圖表說明如何透過 Azure IoT API 傳送的 SMS 訊息或命令喚醒裝置,並將其連線到IoT 中樞以接收命令。

  1. 應用程式會使用 ServiceClient API 將命令傳送至裝置。 ServiceClient 的一個執行個體可以傳送訊息,並針對多個裝置叫用方法。
  2. 應用程式也會透過行動提供者的 SMS 閘道,將 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 維護。 最初是由下列參與者所撰寫。

主體作者:

下一步