共用方式為


傳送和接收雲端到裝置的訊息

Azure IoT 中樞是一項完全受控的服務,可啟用的雙向通訊,包括數百萬個裝置和一個解決方案後端之間的雲端到裝置 (C2D) 訊息。

本文說明如何使用 Azure IoT SDK 來建置下列類型的應用程式:

  • 從 IoT 中樞傳訊佇列接收及處理雲端到裝置訊息的裝置應用程式。

  • 後端應用程式,透過 IoT 中樞訊息佇列將雲端到裝置訊息傳送給單一裝置。

本文旨在補充本文中參考的可執行 SDK 範例。

注意

本文中所述的功能僅適用於 IoT 中樞的標準層。 如需有關基本和標準/免費 IoT 中樞服務層級的詳細資訊,請參閱為您的解決方案選擇適合的 IoT 中樞層 (部分機器翻譯)。

概觀

若要讓裝置應用程式接收雲端到裝置訊息,必須連線到 IoT 中樞,然後設定訊息處理常式來處理傳入訊息。 Azure IoT 中樞裝置 SDK 提供類別和方法,讓裝置可用來接收和處理來自服務的訊息。 本文討論接收訊息的任何裝置應用程式的重要元素,包括:

  • 宣告裝置用戶端物件
  • 連線到 IoT 中樞
  • 從 IoT 中樞訊息佇列擷取訊息
  • 處理訊息,並將通知傳回 IoT 中樞
  • 設定接收訊息重試原則

若要讓後端應用程式傳送雲端到裝置訊息,必須連線到 IoT 中樞,並透過 IoT 中樞訊息佇列傳送訊息。 Azure IoT 中樞服務 SDK 提供應用程式可用來將訊息傳送至裝置的類別和方法。 本文討論傳送訊息至裝置的任何應用程式的重要元素,包括:

  • 宣告服務用戶端物件
  • 連線到 IoT 中樞
  • 建置和傳送此訊息
  • 接收傳遞意見反應
  • 設定傳送訊息重試原則

了解訊息佇列

若要了解雲端到裝置傳訊,請務必了解 IoT 中樞裝置訊息佇列運作方式的一些基本概念。

從解決方案後端應用程式傳送到 IoT 裝置的雲端到裝置訊息會透過 IoT 中樞路由傳送。 解決方案後端應用程式與目標裝置之間沒有直接的點對點傳訊通訊。 IoT 中樞會將傳入訊息放入其訊息佇列中,以供目標 IoT 裝置下載。

為了保證至少一次訊息傳遞,IoT 中樞會在每個裝置佇列保留雲端到裝置訊息。 在 IoT 中樞從佇列中移除訊息之前,裝置必須明確確認訊息已完成。 此方法保證連線失敗和裝置故障能夠恢復。

當 IoT 中樞將訊息放入裝置訊息佇列時,會將訊息狀態設定為加入佇列。 當裝置執行緒從佇列接收訊息時,IoT 中樞會藉由將訊息狀態設定為隱藏來鎖定訊息。 此狀態可防止裝置上的其他執行緒處理相同的訊息。 當裝置執行緒成功完成訊息的處理時,會通知 IoT 中樞,然後 IoT 中樞會將訊息狀態設定為已完成

成功接收和處理訊息的裝置應用程式會顯示完成訊息。 不過,如有必要,裝置也可以:

  • 「拒絕」訊息,這會導致「IoT 中樞」將它設定為 [無法寄出] 狀態。 透過訊息佇列遙測傳輸 (MQTT) 通訊協定連線的裝置無法拒絕雲端到裝置的訊息。
  • 放棄訊息,這會導致 IoT 中樞將訊息放回佇列,並將訊息狀態設定為已排入佇列。 透過 MQTT 通訊協定連線的裝置無法放棄雲端到裝置訊息。

如需雲端到裝置訊息生命週期及 IoT 中樞如何處理雲端到裝置訊息的詳細資訊,請參閱從 IoT 中樞傳送雲端到裝置訊息

建立裝置應用程式

本節說明如何接收雲端到裝置訊息。

裝置用戶端應用程式可以使用兩個選項來接收訊息:

  • 回呼:裝置應用程式會設定非同步訊息處理常式方法,在訊息送達時立即呼叫。
  • 輪詢:裝置應用程式會使用程式碼循環檢查新的 IoT 中樞訊息 (例如 whilefor 迴圈)。 循環會持續執行,並檢查訊息。

必要的裝置 NuGet 套件

以 C# 撰寫的裝置用戶端應用程式需要 Microsoft.Azure.Devices.Client NuGet 套件。

新增這些 using 語句以使用裝置連結庫。

using Microsoft.Azure.Devices.Client;
using Microsoft.Azure.Devices.Shared;

將裝置連線到 IoT 中樞

裝置應用程式可以使用下列方法向 IoT 中樞 進行驗證:

  • 共用存取金鑰
  • X.509 憑證

重要

本文包含使用共用存取簽章 (也稱為對稱金鑰驗證) 連線裝置的步驟。 此驗證方法方便進行測試和評估,但使用 X.509 憑證來驗證裝置是更安全的方法。 若要深入了解,請參閱安全性最佳做法>連線安全性

使用共用存取金鑰進行驗證

DeviceClient 類別會公開在裝置上接收訊息所需的所有方法。

提供連接參數

使用 CreateFromConnectionString 方法,提供 IoT 中樞主要連接字串和裝置識別碼給 DeviceClient。 除了必要的 IoT 中樞主要連接字串之外,CreateFromConnectionString 方法也可以多載以包含這些選擇性參數:

  • transportType - 傳輸通訊協定:HTTP 第 1 版、AMQP 或 MQTT 的變化。 AMQP 是預設值。 若要檢視所有可用的值,請參閱 TransportType 列舉
  • transportSettings - 介面,用來定義 DeviceClientModuleClient 的各種傳輸特定設定。 如需詳細資訊,請參閱 ITransportSettings 介面
  • ClientOptions - 允許在初始化期間設定裝置或模組用戶端執行個體的選項。

此範例會使用 Mqtt 傳輸通訊協定連線到裝置。

static string DeviceConnectionString = "{IoT hub device connection string}";
static deviceClient = null;
deviceClient = DeviceClient.CreateFromConnectionString(DeviceConnectionString, 
   TransportType.Mqtt);

使用 X.509 憑證進行驗證

若要使用 X.509 憑證將裝置連線到 IoT 中樞:

  1. 使用 DeviceAuthenticationWithX509Certificate 建立包含裝置和憑證信息的物件。 DeviceAuthenticationWithX509Certificate 會當做第二個參數傳遞至 DeviceClient.Create (步驟 2)。

  2. 使用 DeviceClient.Create 將裝置連線到使用 X.509 憑證 IoT 中樞。

在這裡範例中,會將裝置和憑證資訊填入傳遞至 DeviceClient.Create的物件中。auth DeviceAuthenticationWithX509Certificate

此範例會顯示憑證輸入參數值做為局部變數,以便清楚起見。 在生產系統中,將敏感性輸入參數儲存在環境變數或其他更安全的儲存位置。 例如,使用 Environment.GetEnvironmentVariable("HOSTNAME") 來讀取主機名環境變數。

RootCertPath = "~/certificates/certs/sensor-thl-001-device.cert.pem";
Intermediate1CertPath = "~/certificates/certs/sensor-thl-001-device.intermediate1.cert.pem";
Intermediate2CertPath = "~/certificates/certs/sensor-thl-001-device.intermediate2.cert.pem";
DevicePfxPath = "~/certificates/certs/sensor-thl-001-device.cert.pfx";
DevicePfxPassword = "1234";
DeviceName = "MyDevice";
HostName = "xxxxx.azure-devices.net";

var chainCerts = new X509Certificate2Collection();
chainCerts.Add(new X509Certificate2(RootCertPath));
chainCerts.Add(new X509Certificate2(Intermediate1CertPath));
chainCerts.Add(new X509Certificate2(Intermediate2CertPath));
using var deviceCert = new X509Certificate2(DevicePfxPath, DevicePfxPassword);
using var auth = new DeviceAuthenticationWithX509Certificate(DeviceName, deviceCert, chainCerts);

using var deviceClient = DeviceClient.Create(
    HostName,
    auth,
    TransportType.Amqp);

如需憑證驗證的詳細資訊,請參閱:

程式碼範例

如需裝置 X.509 憑證驗證的工作範例,請參閱:

回撥

若要在裝置應用程式中接收回呼雲端到裝置訊息,應用程式必須連線到 IoT 中樞,並設定回呼接聽程式來處理傳入訊息。 從 IoT 中樞訊息佇列接收裝置的連入訊息。

使用回呼,裝置應用程式會使用 SetReceiveMessageHandlerAsync 來設定訊息處理常式方法。 接著會呼叫訊息處理常式,然後收到訊息。 建立回呼方法以接收訊息,可移除持續輪詢已接收訊息的需求。

回呼只能使用這些通訊協定:

  • Mqtt
  • Mqtt_WebSocket_Only
  • Mqtt_Tcp_Only
  • Amqp
  • Amqp_WebSocket_Only
  • Amqp_Tcp_only

Http1 通訊協定選項不支援回呼,因為 SDK 方法無論如何都需要輪詢已接收的訊息,這會使回呼原則失敗。

在此範例中,SetReceiveMessageHandlerAsync 設定名為 OnC2dMessageReceivedAsync 的回呼處理常式方法,每次收到訊息時都會呼叫此方法。

// Subscribe to receive C2D messages through a callback (which isn't supported over HTTP).
await deviceClient.SetReceiveMessageHandlerAsync(OnC2dMessageReceivedAsync, deviceClient);
Console.WriteLine($"\n{DateTime.Now}> Subscribed to receive C2D messages over callback.");

輪詢的比較 \(英文\)

輪詢會使用 ReceiveAsync 來檢查訊息。

ReceiveAsync 的呼叫可以採取下列形式:

  • ReceiveAsync() - 等候訊息的預設逾時期間,再繼續。
  • ReceiveAsync (Timespan) - 使用特定逾時從裝置佇列接收訊息。
  • ReceiveAsync (CancellationToken) - 使用取消權杖從裝置佇列接收訊息。 使用取消權杖時,不會使用預設逾時期間。

使用傳輸類型的 HTTP 1 而不使用 MQTT 或 AMQP 時,ReceiveAsync 方法會立即傳回。 使用 HTTP 1 時,針對雲端到裝置訊息支援的模式是裝置以間歇方式連接而不常檢查訊息 (至少每 25 分鐘一次)。 發出更多 HTTP 1 接收會導致「IoT 中樞」對要求進行節流。 如需 MQTT、AMQP 和 HTTP 1 支援之間差異的詳細資訊,請參閱雲端到裝置的通訊指引選擇通訊協定

CompleteAsync 方法

在裝置收到訊息之後,裝置應用程式會呼叫 CompleteAsync 方法來通知 IoT 中樞已成功處理訊息,而且可以從 IoT 中樞裝置佇列安全地移除訊息。 無論使用的傳輸通訊協定為何,裝置在處理順利完成時,應該呼叫此方法。

郵件放棄、拒絕或逾時

使用 AMQP 和 HTTP 第 1 版通訊協定,而不使用 MQTT 通訊協定,裝置也可以:

  • 呼叫 AbandonAsync 來放棄訊息。 這會使得 IoT 中樞將訊息保留在裝置佇列中以供未來使用。
  • 呼叫 RejectAsync 來呼叫拒絕訊息。 這會將訊息從裝置佇列中永久移除。

如果發生導致裝置無法完成、放棄或拒絕訊息的情況,IoT 中樞在固定的逾時期間之後,會將訊息排入佇列以再次傳遞。 基於這個原因,裝置應用程式中的訊息處理邏輯必須是「等冪」,如此一來,多次接收相同訊息才會產生相同的結果。

如需雲端到裝置訊息生命週期及 IoT 中樞如何處理雲端到裝置訊息的詳細資訊,請參閱從 IoT 中樞傳送雲端到裝置訊息

輪詢迴圈

使用輪詢,應用程式會使用程式碼迴圈,重複呼叫 ReceiveAsync 方法,以檢查是否有新訊息,直到停止為止。

如果使用 ReceiveAsync 具有逾時值或預設逾時,在迴圈中每次呼叫 ReceiveAsync 會等候指定的逾時期間。 如果 ReceiveAsync 逾時,則會傳回 null 值,迴圈會繼續。

收到意見反應訊息時,Task 物件會由應該傳遞至 CompleteAsyncReceiveAsync 傳回。 呼叫 CompleteAsync 會通知 IoT 中樞根據 Task 參數,從訊息佇列中刪除指定的訊息。

在此範例中,迴圈會呼叫 ReceiveAsync,直到收到訊息或輪詢迴圈停止為止。

static bool stopPolling = false;

while (!stopPolling)
{
   // Check for a message. Wait for the default DeviceClient timeout period.
   using Message receivedMessage = await _deviceClient.ReceiveAsync();

   // Continue if no message was received
   if (receivedMessage == null)
   {
      continue;
   }
   else  // A message was received
   {
      // Print the message received
      Console.WriteLine($"{DateTime.Now}> Polling using ReceiveAsync() - received message with Id={receivedMessage.MessageId}");
      PrintMessage(receivedMessage);

      // Notify IoT Hub that the message was received. IoT Hub will delete the message from the message queue.
      await _deviceClient.CompleteAsync(receivedMessage);
      Console.WriteLine($"{DateTime.Now}> Completed C2D message with Id={receivedMessage.MessageId}.");
   }

   // Check to see if polling loop should end
   stopPolling = ShouldPollingstop ();
}

接收訊息重試原則

您可以使用 DeviceClient.SetRetryPolicy 來定義裝置用戶端訊息重試原則。

訊息重試逾時會儲存在 DeviceClient.OperationTimeoutInMilliseconds 屬性中。

SDK 接收訊息範例

.NET/C# SDK 包含訊息接收範例,其中包含本節所述的接收訊息方法。

建立後端應用程式

本節說明使用 Azure IoT SDK for .NET 中的 ServiceClient 類別,將訊息從解決方案後端應用程式傳送至 IoT 裝置的基本程式碼。 如先前所述,解決方案後端應用程式會連線到 IoT 中樞,並將訊息傳送至使用目的地裝置編碼的 IoT 中樞。 IoT 中樞會將傳入訊息儲存至其訊息佇列,而訊息會從 IoT 中樞訊息佇列傳遞至目標裝置。

解決方案後端應用程式也可以針對傳送至 IoT 中樞的訊息,要求並接收傳遞意見反應,該訊息會透過訊息佇列傳送裝置。

新增服務 NuGet 套件

後端服務應用程式需要 Microsoft.Azure.Devices NuGet 套件。

連線至 IoT 中樞

您可以使用下列方法將後端服務連線到 IoT 中樞:

  • 共用存取原則
  • Microsoft Entra

重要

本文包含使用共用存取簽章連線至服務的步驟。 此驗證方法方便進行測試和評估,但使用 Microsoft Entra ID 或受控識別向服務進行驗證是更安全的方法。 若要深入了解,請參閱安全性最佳做法 > 雲端安全性

使用共用存取原則進行連線

提供連線字串

使用 CreateFromConnectionString 將後端應用程式連線到裝置。 除了必要的 IoT 中樞主要連接字串之外,CreateFromConnectionString 方法也可以多載以包含這些選擇性參數:

  • transportType - AmqpAmqp_WebSocket_Only
  • transportSettings - Service Client 的 AMQP 和 HTTP Proxy 設定。
  • ServiceClientOptions - 允許在初始化期間設定服務用戶端執行個體的選項。 如需詳細資訊,請參閱 ServiceClientOptions

此範例會使用 IoT 中樞 連接字串 和預設Amqp傳輸來建立 ServiceClient 物件。

static string connectionString = "{your IoT hub connection string}";
serviceClient = ServiceClient.CreateFromConnectionString(connectionString);

使用 Microsoft Entra 進行連線

使用 Microsoft Entra 的後端應用程式必須先成功驗證並取得安全性令牌認證,才能連線到 IoT 中樞。 此令牌會傳遞至 IoT 中樞 連接方法。 如需設定和使用 Microsoft Entra 進行 IoT 中樞 的一般資訊,請參閱使用 Microsoft Entra 識別符控制對 IoT 中樞 的存取。

設定 Microsoft Entra 應用程式

您必須設定已針對您慣用的驗證認證設定Microsoft Entra 應用程式。 應用程式包含參數,例如後端應用程式用來驗證的客戶端密碼。 可用的應用程式驗證群組態如下:

  • 用戶端密碼
  • [MSSQLSERVER 的通訊協定內容]
  • 同盟身分識別認證

Microsoft Entra 應用程式可能需要特定角色許可權,視執行的作業而定。 例如,需要 IoT 中樞 對應項參與者,才能啟用 IoT 中樞 裝置和模塊對應項的讀取和寫入存取權。 如需詳細資訊,請參閱使用 Azure RBAC 角色指派來管理 IoT 中樞 的存取權。

如需設定 Microsoft Entra 應用程式的詳細資訊,請參閱快速入門:向 Microsoft 身分識別平台 註冊應用程式。

使用 DefaultAzureCredential 進行驗證

使用 Microsoft Entra 來驗證後端應用程式最簡單的方式是使用 DefaultAzureCredential,但建議在生產環境中使用不同的方法,包括特定TokenCredential或剖析。ChainedTokenCredential 為了簡單起見,本節說明使用 DefaultAzureCredential 和用戶端密碼的驗證。 如需使用 DefaultAzureCredential之優缺點的詳細資訊,請參閱 DefaultAzureCredential 的使用指引。

DefaultAzureCredential 支援不同的驗證機制,並根據執行中的環境來判斷適當的認證類型。 它會嘗試依序使用多個認證類型,直到找到有效的認證為止。

Microsoft Entra 需要下列 NuGet 套件和對應的 using 語句:

  • Azure.Core
  • Azure.Identity
using Azure.Core;
using Azure.Identity;

在此範例中,Microsoft Entra 應用程式註冊客戶端密碼、用戶端標識碼和租使用者標識元會新增至環境變數。 這些環境變數是用來 DefaultAzureCredential 驗證應用程式。 成功Microsoft Entra 驗證的結果是傳遞至 IoT 中樞 連線方法的安全性令牌認證。

string clientSecretValue = "xxxxxxxxxxxxxxx";
string clientID = "xxxxxxxxxxxxxx";
string tenantID = "xxxxxxxxxxxxx";

Environment.SetEnvironmentVariable("AZURE_CLIENT_SECRET", clientSecretValue);
Environment.SetEnvironmentVariable("AZURE_CLIENT_ID", clientID);
Environment.SetEnvironmentVariable("AZURE_TENANT_ID", tenantID);

TokenCredential tokenCredential = new DefaultAzureCredential();

接著,產生的 TokenCredential 可以傳遞給任何接受 Microsoft Entra 認證的 SDK 用戶端的連線至 IoT 中樞 方法:

在此範例中, TokenCredential 會傳遞 至 ServiceClient.Create 以建立 ServiceClient 連接物件。

string hostname = "xxxxxxxxxx.azure-devices.net";
using var serviceClient = ServiceClient.Create(hostname, tokenCredential, TransportType.Amqp);

在此範例中, TokenCredential 會傳遞 至 RegistryManager.Create 以建立 RegistryManager 物件。

string hostname = "xxxxxxxxxx.azure-devices.net";
registryManager = RegistryManager.Create(hostname, tokenCredential);
程式碼範例

如需Microsoft Entra 服務驗證的運作範例,請參閱 角色型驗證範例

傳送非同步雲端到裝置訊息

使用 sendAsync,透過雲端將非同步訊息從應用程式傳送至裝置。 呼叫是使用 AMQP 通訊協定進行。

sendAsync 使用這些參數:

  • deviceID - 目標裝置的字串識別碼。
  • message - 雲端對裝置訊息。 訊息的類型為訊息,而且可以據以格式化。
  • timeout - 選用的逾時值。 如未指定,預設為一分鐘。

此範例會將測試訊息傳送至目標裝置,其逾時值為 10 秒。

string targetDevice = "Device-1";
static readonly TimeSpan operationTimeout = TimeSpan.FromSeconds(10);
var commandMessage = new
Message(Encoding.ASCII.GetBytes("Cloud to device message."));
await serviceClient.SendAsync(targetDevice, commandMessage, operationTimeout);

接收傳遞意見反應

傳送程式可向 IoT 中樞要求每個雲端到裝置訊息的傳遞 (或到期) 通知。 此動作可讓傳送程式使用通知、重試或補償邏輯。 訊息意見反應作業和屬性的完整描述會在訊息意見反應描述。

若要接收訊息傳遞意見反應:

  • 建立 feedbackReceiver 物件
  • 使用 Ack 參數傳送訊息
  • 等候接收意見反應

建立 feedbackReceiver 物件

呼叫 GetFeedbackReceiver,以建立 FeedbackReceiver 物件。 FeedbackReceiver 包含服務可用來執行意見反應接收作業的方法。

var feedbackReceiver = serviceClient.GetFeedbackReceiver();

使用 Ack 參數傳送訊息

每個訊息都必須包含傳遞通知的值,Ack 屬性,才能接收傳遞意見反應。 Ack 屬性可以是下列值之一:

  • none (預設值):不會產生任何意見反應訊息。

  • Positive:如果訊息已完成,則接收意見反應訊息。

  • Negative:如果訊息已過期 (或達到最大傳遞計數),則接收意見反應訊息,而不會由裝置完成。

  • FullPositiveNegative 結果的意見反應。

在本範例中,Ack 屬性設為 Full,針對一個訊息要求正面或負面的訊息傳遞意見反應。

var commandMessage = new
Message(Encoding.ASCII.GetBytes("Cloud to device message."));
commandMessage.Ack = DeliveryAcknowledgement.Full;
await serviceClient.SendAsync(targetDevice, commandMessage);

等候接收意見反應

定義 CancellationToken。 然後在迴圈中,重複呼叫 ReceiveAsync,檢查傳遞意見反應訊息。 每次呼叫 ReceiveAsync 會等候為 ServiceClient 物件定義的逾時期間。

  • 如果 ReceiveAsync 逾時過期且未收到任何訊息,ReceiveAsync 會傳回 null,迴圈會繼續。
  • 如果收到意見反應訊息,Task 物件會由應該傳遞至 CompleteAsync 以及取消權杖的 ReceiveAsync 傳回。 呼叫 CompleteAsync 會根據 Task 參數,從訊息佇列中刪除指定傳送的訊息。
  • 如有需要,接收程式碼可以呼叫 AbandonAsync,將傳送訊息放回佇列。
var feedbackReceiver = serviceClient.GetFeedbackReceiver();
// Define the cancellation token.
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;
// Call ReceiveAsync, passing the token. Wait for the timout period.
var feedbackBatch = await feedbackReceiver.ReceiveAsync(token);
if (feedbackBatch == null) continue;

本範例顯示包含這些步驟的方法。

private async static void ReceiveFeedbackAsync()
{
      var feedbackReceiver = serviceClient.GetFeedbackReceiver();

      Console.WriteLine("\nReceiving c2d feedback from service");
      while (true)
      {
         // Check for messages, wait for the timeout period.
         var feedbackBatch = await feedbackReceiver.ReceiveAsync();
         // Continue the loop if null is received after a timeout.
         if (feedbackBatch == null) continue;

         Console.ForegroundColor = ConsoleColor.Yellow;
         Console.WriteLine("Received feedback: {0}",
            string.Join(", ", feedbackBatch.Records.Select(f => f.StatusCode)));
         Console.ResetColor();

         await feedbackReceiver.CompleteAsync(feedbackBatch);
      }
   }

請注意,本意見反應接收模式,與在裝置應用程式中接收雲端到裝置訊息的模式類似。

服務用戶端重新連線

發生例外狀況時,服務用戶端會將該資訊轉送至呼叫的應用程式。 此時,建議您檢查例外狀況詳細資料,並採取必要的動作。

例如:

  • 如果是網路例外狀況,您可以重試作業。
  • 如果是安全性例外狀況 (未經授權的例外狀況),請檢查您的認證,並確定其為最新狀態。
  • 如果是超出節流/配額的例外狀況,請監視和/或修改傳送要求的頻率,或更新中樞執行個體級別單位。 請參閱 IoT 中樞配額和節流深入了解。

傳送訊息重試原則

您可以使用 ServiceClient.SetRetryPolicy 來定義 ServiceClient 訊息重試原則。

SDK 傳送訊息範例

.NET/C# SDK 包含訊息傳送範例,其中包含本節所述的服務用戶端方法。

建立裝置應用程式

本節說明如何從適用於 Java 的 Azure IoT SDK 使用 DeviceClient 類別來接收雲端到裝置訊息。

若要讓 Java 型裝置應用程式接收雲端到裝置訊息,必須連線到 IoT 中樞,然後設定來自 IoT 中輸的回呼接聽程式和訊息處理常式來處理傳入訊息。

匯入 Azure IoT Java SDK 程式庫

本文所參考的程式碼會使用這些 SDK 程式庫。

import com.microsoft.azure.sdk.iot.device.*;
import com.microsoft.azure.sdk.iot.device.exceptions.IotHubClientException;
import com.microsoft.azure.sdk.iot.device.transport.IotHubConnectionStatus;

將裝置連線到 IoT 中樞

裝置應用程式可以使用下列方法來向 IoT 中樞 進行驗證:

  • 共用存取金鑰
  • X.509 憑證

重要

本文包含使用共用存取簽章 (也稱為對稱金鑰驗證) 連線裝置的步驟。 此驗證方法方便進行測試和評估,但使用 X.509 憑證來驗證裝置是更安全的方法。 若要深入了解,請參閱安全性最佳做法>連線安全性

使用共用存取金鑰進行驗證

DeviceClient 物件具現化需要下列參數:

  • connString - IoT 裝置連接字串。 連接字串是一組以 ';', 分隔的索引鍵/值組,索引鍵和值則以 '=' 分隔。 這應該包含這些索引鍵的值:HostName, DeviceId, and SharedAccessKey
  • 傳輸通訊協定 - DeviceClient 連線可以使用下列其中一個 IoTHubClientProtocol 傳輸通訊協定。 AMQP 功能最廣泛,可讓您經常檢查訊息,並允許拒絕和取消訊息。 MQTT 不支援訊息拒絕或放棄方法:
    • AMQPS
    • AMQPS_WS
    • HTTPS
    • MQTT
    • MQTT_WS

例如:

static string connectionString = "{IOT hub device connection string}";
static protocol = IotHubClientProtocol.AMQPS;
DeviceClient client = new DeviceClient(connectionString, protocol);

使用 X.509 憑證進行驗證

若要使用 X.509 憑證將裝置連線到 IoT 中樞:

  1. 使用 buildSSLContext 建置 SSLContext 物件。
  2. SSLContext 資訊新增至 ClientOptions 物件。
  3. 使用ClientOptions資訊呼叫 DeviceClient 以建立裝置對 IoT 中樞 連線。

此範例會顯示憑證輸入參數值做為局部變數,以便清楚起見。 在生產系統中,將敏感性輸入參數儲存在環境變數或其他更安全的儲存位置。 例如,使用 Environment.GetEnvironmentVariable("PUBLICKEY") 來讀取公鑰憑證字串環境變數。

private static final String publicKeyCertificateString =
        "-----BEGIN CERTIFICATE-----\n" +
        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
        "-----END CERTIFICATE-----\n";

//PEM encoded representation of the private key
private static final String privateKeyString =
        "-----BEGIN EC PRIVATE KEY-----\n" +
        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
        "-----END EC PRIVATE KEY-----\n";

SSLContext sslContext = SSLContextBuilder.buildSSLContext(publicKeyCertificateString, privateKeyString);
ClientOptions clientOptions = ClientOptions.builder().sslContext(sslContext).build();
DeviceClient client = new DeviceClient(connString, protocol, clientOptions);

如需憑證驗證的詳細資訊,請參閱:

程式碼範例

如需裝置 X.509 憑證驗證的工作範例,請參閱:

設立訊息回呼方式

使用 setMessageCallback 方法來定義從 IoT 中樞接收訊息時收到通知的訊息處理常式方法。

setMessageCallback 包括這些參數:

  • callback - 回呼方法名稱。 可以是 null
  • context - 選擇性類型 object 內容。 如未指定,使用 null

在這裡範例中,名為 MessageCallback 且沒有內容參數的 callback 方法會傳遞至 setMessageCallback

client.setMessageCallback(new MessageCallback(), null);

建立訊息回呼處理常式

回呼訊息處理常式會接收並處理從 IoT 中樞訊息佇列傳遞的傳入訊息。

在此範例中,訊息處理常式會處理傳入訊息,然後傳回 IotHubMessageResult.COMPLETE是。 IotHubMessageResult.COMPLETE 傳回值會通知 IoT 中樞訊息已成功處理,而且可以從裝置佇列安全地移除訊息。 裝置應該會在處理成功完成時傳回 IotHubMessageResult.COMPLETE,通知 IoT 中樞應該從訊息佇列中移除訊息,而不論其所使用的通訊協定為何。

  protected static class MessageCallback implements com.microsoft.azure.sdk.iot.device.MessageCallback
  {
      public IotHubMessageResult onCloudToDeviceMessageReceived(Message msg, Object context)
      {
          System.out.println(
                  "Received message with content: " + new String(msg.getBytes(), Message.DEFAULT_IOTHUB_MESSAGE_CHARSET));
          // Notify IoT Hub that the message
          return IotHubMessageResult.COMPLETE;
      }
  }

郵件放棄和拒絕選項

雖然應該成功接收大量傳入裝置的訊息,並導致 IotHubMessageResult.COMPLETE,但可能需要放棄或拒絕訊息。

  • 透過 AMQP 和 HTTPS,但不是透過 MQTT,應用程式可以:
    • IotHubMessageResult.ABANDON 訊息。 IoT 中樞會重新佇列,稍後再傳送。
    • IotHubMessageResult.REJECT 訊息。 IoT 中樞不會重新佇列訊息,並永久移除訊息佇列中的訊息。
  • 使用 MQTTMQTT_WS 的用戶端無法 ABANDONREJECT 訊息。

如果發生導致裝置無法完成、放棄或拒絕訊息的情況,IoT 中樞在固定的逾時期間之後,會將訊息排入佇列以再次傳遞。 基於這個原因,裝置應用程式中的訊息處理邏輯必須是「等冪」,如此一來,多次接收相同訊息才會產生相同的結果。

如需雲端到裝置訊息生命週期及 IoT 中樞如何處理雲端到裝置訊息的詳細資訊,請參閱從 IoT 中樞傳送雲端到裝置訊息

注意

如果您使用 HTTPS 而不是使用 MQTT 或 AMQP 作為傳輸,則 DeviceClient 執行個體將不會經常 (至少每隔 25 分鐘) 檢查 IoT 中樞是否有訊息。 如需 MQTT、AMQP 和 HTTPS 支援之間差異的詳細資訊,請參閱雲端到裝置的通訊指引選擇通訊協定

建立訊息狀態回呼方法

應用程式可以使用 registerConnectionStatusChangeCallback,註冊裝置連線狀態變更時要執行的回呼方法。 如此一來,應用程式就可以偵測已關閉的訊息連線,並嘗試重新連線。

在此範例中,IotHubConnectionStatusChangeCallbackLogger 註冊為聯機狀態變更回呼方法。

client.registerConnectionStatusChangeCallback(new IotHubConnectionStatusChangeCallbackLogger(), new Object());

會引發回呼並傳遞 ConnectionStatusChangeContext 物件。

呼叫 connectionStatusChangeContext.getNewStatus() 以目前連接狀態。

IotHubConnectionStatus status = connectionStatusChangeContext.getNewStatus();

傳回的連接狀態可以是下列其中一個值:

  • IotHubConnectionStatus.DISCONNECTED
  • IotHubConnectionStatus.DISCONNECTED_RETRYING
  • IotHubConnectionStatus.CONNECTED

呼叫 connectionStatusChangeContext.getNewStatusReason() 以取得連線狀態變更的原因。

IotHubConnectionStatusChangeReason statusChangeReason = connectionStatusChangeContext.getNewStatusReason();

呼叫 connectionStatusChangeContext.getCause() 以找到連線狀態變更的原因。 如果沒有可用的資訊,getCause() 可能會傳回 null

Throwable throwable = connectionStatusChangeContext.getCause();
if (throwable != null)
    throwable.printStackTrace();

如需示範如何擷取狀態變更回呼方法連線狀態變更狀態、裝置狀態變更原因和內容的完整範例,請參閱本文 SDK 接收訊息範例一節中列出的 HandleMessages 範例。

開啟裝置與 IoT 中樞之間的連線

使用開啟來建立裝置與 IoT 中樞之間的連線。 裝置現在可以以非同步方式從 IoT 中樞來回傳送和接收訊息。 如果用戶端已經開啟,方法就不會執行任何動作。

client.open(true);

SDK 接收訊息範例

HandleMessages: 一個 Microsoft Azure IoT SDK for Java 隨附的範例裝置應用程式,會連線到您的 IoT 中樞並接收雲端到裝置的訊息。

建立後端應用程式

本節說明如何從適用於 Java 的 Azure IoT SDK 使用 ServiceClient 類別傳送雲端到裝置訊息。 解決方案後端應用程式會連線到 IoT 中樞,並將訊息傳送至使用目的地裝置編碼的 IoT 中樞。 IoT 中樞會將傳入訊息儲存至其訊息佇列,而訊息會從 IoT 中樞訊息佇列傳遞至目標裝置。

解決方案後端應用程式也可以針對傳送至 IoT 中樞的訊息,要求並接收傳遞意見反應,該訊息會透過訊息佇列傳送裝置。

新增相依性陳述式

新增相依性可在應用程式中使用 iothub-java-service-client 套件與 IoT 中樞服務進行通訊:

<dependency>
  <groupId>com.microsoft.azure.sdk.iot</groupId>
  <artifactId>iot-service-client</artifactId>
  <version>1.7.23</version>
</dependency>

新增 import 陳述式

新增這些 import 陳述式,以使用 Azure IoT Java SDK 和例外狀況處理常式。

import com.microsoft.azure.sdk.iot.service.*;
import java.io.IOException;
import java.net.URISyntaxException;

連線至 IoT 中樞

您可以使用下列方法將後端服務連線到 IoT 中樞:

  • 共用存取原則
  • Microsoft Entra

重要

本文包含使用共用存取簽章連線至服務的步驟。 此驗證方法方便進行測試和評估,但使用 Microsoft Entra ID 或受控識別向服務進行驗證是更安全的方法。 若要深入了解,請參閱安全性最佳做法 > 雲端安全性

使用共用存取原則進行連線

定義連線通訊協定

使用 IotHubServiceClientProtocol 來定義服務用戶端用來與 IoT 中樞通訊的應用程式層通訊協定。

IotHubServiceClientProtocol 只接受 AMQPSAMQPS_WS 列舉。

IotHubServiceClientProtocol protocol = IotHubServiceClientProtocol.AMQPS;
建立 ServiceClient 物件

建立 ServiceClient 物件,並提供 Iot 中樞連接字串和通訊協定。

String connectionString = "{yourhubconnectionstring}";
ServiceClient serviceClient (connectionString, protocol);
開啟應用程式與 IoT 中樞之間的連線

開啟 AMQP 傳送者連線。 此方法會建立應用程式與 IoT 中樞之間的連線。

serviceClient.open();

使用 Microsoft Entra 進行連線

使用 Microsoft Entra 的後端應用程式必須先成功驗證並取得安全性令牌認證,才能連線到 IoT 中樞。 此令牌會傳遞至 IoT 中樞 連接方法。 如需設定和使用 Microsoft Entra 進行 IoT 中樞 的一般資訊,請參閱使用 Microsoft Entra 識別符控制對 IoT 中樞 的存取。

如需 Java SDK 驗證的概觀,請參閱 使用 Java 和 Azure 身分識別進行 Azure 驗證。

為了簡單起見,本節著重於使用用戶端密碼描述驗證。

設定 Microsoft Entra 應用程式

您必須設定已針對您慣用的驗證認證設定Microsoft Entra 應用程式。 應用程式包含參數,例如後端應用程式用來驗證的客戶端密碼。 可用的應用程式驗證群組態如下:

  • 用戶端密碼
  • [MSSQLSERVER 的通訊協定內容]
  • 同盟身分識別認證

Microsoft Entra 應用程式可能需要特定角色許可權,視執行的作業而定。 例如,需要 IoT 中樞 對應項參與者,才能對 IoT 中樞 裝置和模組對應項啟用讀取和寫入存取權。 如需詳細資訊,請參閱使用 Azure RBAC 角色指派來管理 IoT 中樞 的存取權。

如需設定Microsoft Entra 應用程式的詳細資訊,請參閱快速入門:使用 Microsoft 身分識別平台 註冊應用程式。

使用 DefaultAzureCredential 進行驗證

使用 Microsoft Entra 來驗證後端應用程式最簡單的方式是使用 DefaultAzureCredential,但建議在生產環境中使用不同的方法,包括特定TokenCredential或剖析。ChainedTokenCredential 如需使用 DefaultAzureCredential之優缺點的詳細資訊,請參閱 適用於 Java 的 Azure 身分識別用戶端連結庫中的認證鏈結。

DefaultAzureCredential 支援不同的驗證機制,並根據執行中的環境來判斷適當的認證類型。 它會嘗試依序使用多個認證類型,直到找到有效的認證為止。

您可以使用 DefaultAzureCredentialBuilder 來驗證Microsoft Entra 應用程式認證。 將用戶端秘密 tenantID、clientID 和用戶端秘密值等聯機參數儲存為環境變數。 TokenCredential建立 之後,將它傳遞至 ServiceClient 或其他產生器做為 'credential' 參數。

在此範例中,DefaultAzureCredentialBuilder嘗試從 DefaultAzureCredential 中所述的清單驗證連線。 成功Microsoft Entra 驗證的結果是傳遞至 ServiceClient建構函式的安全性令牌認證。

TokenCredential defaultAzureCredential = new DefaultAzureCredentialBuilder().build();
使用 ClientSecretCredentialBuilder 進行驗證

您可以使用 ClientSecretCredentialBuilder ,使用用戶端秘密資訊建立認證。 如果成功,這個方法會傳回可傳遞至 ServiceClient 或其他產生器做為 'credential' 參數的 TokenCredential。

在此範例中,Microsoft Entra 應用程式註冊客戶端密碼、用戶端標識碼和租使用者標識碼值已新增至環境變數。 這些環境變數是用來 ClientSecretCredentialBuilder 建置認證。

string clientSecretValue = System.getenv("AZURE_CLIENT_SECRET");
string clientID = System.getenv("AZURE_CLIENT_ID");
string tenantID = System.getenv("AZURE_TENANT_ID");

TokenCredential credential =
     new ClientSecretCredentialBuilder()
          .tenantId(tenantID)
          .clientId(clientID)
          .clientSecret(clientSecretValue)
          .build();
其他驗證類別

Java SDK 也包含這些類別,這些類別會使用 Microsoft Entra 來驗證後端應用程式:

程式碼範例

如需Microsoft Entra 服務驗證的工作範例,請參閱 角色型驗證範例

開啟訊息傳遞意見反應的意見反應接收者

您可以使用 FeedbackReceiver,將訊息傳遞至 IoT 中樞的意見反應。 FeedbackReceiver 是特製接收者,其 Receive 方法會傳回 FeedbackBatch,而不是 Message

在此範例中,會建立 FeedbackReceiver 物件,並呼叫 open() 陳述式來等候意見反應。

FeedbackReceiver feedbackReceiver = serviceClient
  .getFeedbackReceiver();
if (feedbackReceiver != null) feedbackReceiver.open();

新增訊息屬性

您可以選擇性地使用 setProperties 來新增訊息屬性。 這些屬性包含在傳送至裝置的訊息中,而且可在收到時由裝置應用程式擷取。

Map<String, String> propertiesToSend = new HashMap<String, String>();
propertiesToSend.put(messagePropertyKey,messagePropertyKey);
messageToSend.setProperties(propertiesToSend);

建立並傳送非同步訊息

Message 物件會儲存要傳送的訊息。 在此範例中,會傳遞「雲端到裝置訊息」。

使用 setDeliveryAcknowledgement 來要求傳遞/未傳遞至 IoT 中樞訊息佇列通知。 在此範例中,要求的通知 Full 為傳遞或未傳遞。

使用 SendAsync,將非同步訊息從用戶端傳送至裝置。 或者,您可以使用 Send (非同步) 方法,但此函數會在內部同步處理,一次只允許一個傳送作業。 訊息會從應用程式傳遞至 IoT 中樞。 IoT 中樞會將訊息放入訊息佇列中,準備好傳遞至目標裝置。

Message messageToSend = new Message("Cloud to device message.");
messageToSend.setDeliveryAcknowledgementFinal(DeliveryAcknowledgement.Full);
serviceClient.sendAsync(deviceId, messageToSend);

接收訊息傳遞意見反應

從應用程式傳送訊息之後,應用程式可以呼叫接收,且沒有逾時值。 如果未提供逾時值,則會使用預設逾時。 這會傳回 FeedbackBatch 物件,其中包含可以檢查的訊息傳遞意見反應屬性。

此範例會建立 FeedbackBatch 接收者,並呼叫 getEnqueuedTimeUtc ,並列印訊息加入佇列的時間。

FeedbackBatch feedbackBatch = feedbackReceiver.receive(10000);
if (feedbackBatch != null) {
  System.out.println("Message feedback received, feedback time: "
    + feedbackBatch.getEnqueuedTimeUtc().toString());
}

SDK 傳送訊息範例

有兩個傳送訊息範例:

建立裝置應用程式

本節說明如何接收雲端到裝置訊息。

IoTHubDeviceClient 類別包含方法,可從裝置建立同步連線到 Azure IoT 中樞,並從 IoT 中樞接收訊息。

必須安裝 azure-iot-device 連結庫,才能建立裝置應用程式。

pip install azure-iot-device

若要讓 Python 型裝置應用程式接收雲端到裝置訊息,必須連線到 IoT 中樞,然後設定來自 IoT 中輸的回呼訊息處理常式來處理傳入訊息。

裝置匯入語句

新增此程式代碼以從 azure.iot.device SDK 匯入 IoTHubDeviceClient 函式。

from azure.iot.device import IoTHubDeviceClient

將裝置連線到 IoT 中樞

裝置應用程式可以使用下列方法來向 IoT 中樞 進行驗證:

  • 共用存取金鑰
  • X.509 憑證

重要

本文包含使用共用存取簽章 (也稱為對稱金鑰驗證) 連線裝置的步驟。 此驗證方法方便進行測試和評估,但使用 X.509 憑證來驗證裝置是更安全的方法。 若要深入了解,請參閱安全性最佳做法>連線安全性

使用共用存取金鑰進行驗證

若要將裝置連線至 IoT 中樞:

  1. 呼叫 create_from_connection_string 以新增裝置主要 連接字串。
  2. 呼叫 connect 以連線裝置用戶端。

例如:

# Add your IoT hub primary connection string
CONNECTION_STRING = "{Device primary connection string}"
device_client = IoTHubDeviceClient.create_from_connection_string(CONNECTION_STRING)

# Connect the client
device_client.connect()

使用 X.509 憑證進行驗證

若要使用 X.509 憑證將裝置連線到 IoT 中樞:

  1. 使用 create_from_x509_certificate 新增 X.509 憑證參數
  2. 呼叫 connect 以連線裝置用戶端

此範例會顯示憑證輸入參數值做為局部變數,以便清楚起見。 在生產系統中,將敏感性輸入參數儲存在環境變數或其他更安全的儲存位置。 例如,使用 os.getenv("HOSTNAME") 來讀取主機名環境變數。

# The Azure IoT hub name
hostname = "xxxxx.azure-devices.net"

# The device that has been created on the portal using X509 CA signing or self-signing capabilities
device_id = "MyDevice"

# The X.509 certificate file name
cert_file = "~/certificates/certs/sensor-thl-001-device.cert.pfx"
key_file = "~/certificates/certs/sensor-thl-001-device.cert.key"
# The optional certificate pass phrase
pass_phrase = "1234"

x509 = X509(
    cert_file,
    key_file,
    pass_phrase,
)

# The client object is used to interact with your Azure IoT hub.
device_client = IoTHubDeviceClient.create_from_x509_certificate(
    hostname=hostname, device_id=device_id, x509=x509
)

# Connect to IoT Hub
await device_client.connect()

如需憑證驗證的詳細資訊,請參閱:

程式碼範例

如需裝置 X.509 憑證驗證的工作範例,請參閱 Async 中樞案例檔名以 x509 結尾的範例。

控制代碼重新連線

IoTHubDeviceClient 預設會嘗試重新建立已卸除的連線。 重新連線行為是由 IoTHubDeviceClient connection_retryconnection_retry_interval 參數所控管。

建立訊息處理常式

建立訊息處理程式函式來處理裝置的傳入訊息。 這會由 on_message_received (下一個步驟) 指派為回呼訊息處理程式。

本範例中,在收到訊息時,便會呼叫 message_handler。 訊息屬性 (.items) 會使用迴圈列印至主控台。

def message_handler(message):
    global RECEIVED_MESSAGES
    RECEIVED_MESSAGES += 1
    print("")
    print("Message received:")

    # print data from both system and application (custom) properties
    for property in vars(message).items():
        print ("    {}".format(property))

    print("Total calls received: {}".format(RECEIVED_MESSAGES))

指派訊息處理常式

使用 on_message_received 方法來指派訊息處理程式方法。

在此範例中,名為 message_handler 的訊息處理常式方法會附加至 IoTHubDeviceClient client 物件。 client 物件會等候接收來自 IoT 中樞的雲端到裝置訊息。 此程式碼會等候最多 300 秒 (5 分鐘) 的訊息,或在按下鍵盤按鍵時結束。

try:
    # Attach the handler to the client
    client.on_message_received = message_handler

    while True:
        time.sleep(300)
except KeyboardInterrupt:
    print("IoT Hub C2D Messaging device sample stopped")
finally:
    # Graceful exit
    print("Shutting down IoT Hub Client")
    client.shutdown()

SDK 接收訊息範例

接收訊息 - 接收從 Azure IoT 中樞傳送到裝置的雲端到裝置 (C2D) 訊息。

建立後端應用程式

本節說明如何傳送雲端到裝置的訊息。 解決方案後端應用程式會連線到 IoT 中樞,並將訊息傳送至使用目的地裝置編碼的 IoT 中樞。 IoT 中樞會將傳入訊息儲存至其訊息佇列,而訊息會從 IoT 中樞訊息佇列傳遞至目標裝置。

IoTHubRegistryManager 類別會公開建立後端應用程式以與服務中的雲端到裝置訊息互動所需的所有方法。 必須安裝 azure-iot-hub 連結庫,才能建立後端服務應用程式。

pip install azure-iot-hub

匯入 IoTHubRegistryManager 物件

加入下列 import 陳述式。 IoTHubRegistryManager 包含 IoT 中樞登錄管理員作業的 API。

from azure.iot.hub import IoTHubRegistryManager

連線至 IoT 中樞

您可以使用下列方法,將後端服務連線到 IoT 中樞:

  • 共用存取原則
  • Microsoft Entra

重要

本文包含使用共用存取簽章連線至服務的步驟。 此驗證方法方便進行測試和評估,但使用 Microsoft Entra ID 或受控識別向服務進行驗證是更安全的方法。 若要深入了解,請參閱安全性最佳做法 > 雲端安全性

使用共用存取原則進行連線

使用 from_connection_string 連線到 IoT 中樞。

例如:

IoTHubConnectionString = "{IoT hub service connection string}"
registry_manager = IoTHubRegistryManager.from_connection_string(IoTHubConnectionString)

使用 Microsoft Entra 進行連線

使用 Microsoft Entra 的後端應用程式必須先成功驗證並取得安全性令牌認證,才能連線到 IoT 中樞。 此令牌會傳遞至 IoT 中樞 連接方法。 如需設定和使用 Microsoft Entra 進行 IoT 中樞 的一般資訊,請參閱使用 Microsoft Entra 識別符控制對 IoT 中樞 的存取。

設定 Microsoft Entra 應用程式

您必須設定已針對您慣用的驗證認證設定Microsoft Entra 應用程式。 應用程式包含參數,例如後端應用程式用來驗證的客戶端密碼。 可用的應用程式驗證群組態如下:

  • 用戶端密碼
  • [MSSQLSERVER 的通訊協定內容]
  • 同盟身分識別認證

Microsoft Entra 應用程式可能需要特定角色許可權,視執行的作業而定。 例如,需要 IoT 中樞 對應項參與者,才能啟用 IoT 中樞 裝置和模塊對應項的讀取和寫入存取權。 如需詳細資訊,請參閱使用 Azure RBAC 角色指派來管理 IoT 中樞 的存取權。

如需設定 Microsoft Entra 應用程式的詳細資訊,請參閱快速入門:向 Microsoft 身分識別平台 註冊應用程式。

使用 DefaultAzureCredential 進行驗證

使用 Microsoft Entra 來驗證後端應用程式最簡單的方式是使用 DefaultAzureCredential,但建議在生產環境中使用不同的方法,包括特定TokenCredential或剖析。ChainedTokenCredential 為了簡單起見,本節說明使用 DefaultAzureCredential 和用戶端密碼的驗證。 如需使用 DefaultAzureCredential之優缺點的詳細資訊,請參閱 DefaultAzureCredential 的使用指引。

DefaultAzureCredential 支援不同的驗證機制,並根據執行中的環境來判斷適當的認證類型。 它會嘗試依序使用多個認證類型,直到找到有效的認證為止。

Microsoft Entra 需要下列 NuGet 套件和對應的 using 語句:

  • Azure.Core
  • Azure.Identity
using Azure.Core;
using Azure.Identity;

在此範例中,Microsoft Entra 應用程式註冊客戶端密碼、用戶端標識碼和租使用者標識元會新增至環境變數。 這些環境變數是用來 DefaultAzureCredential 驗證應用程式。 成功Microsoft Entra 驗證的結果是傳遞至 IoT 中樞 連線方法的安全性令牌認證。

string clientSecretValue = "xxxxxxxxxxxxxxx";
string clientID = "xxxxxxxxxxxxxx";
string tenantID = "xxxxxxxxxxxxx";

Environment.SetEnvironmentVariable("AZURE_CLIENT_SECRET", clientSecretValue);
Environment.SetEnvironmentVariable("AZURE_CLIENT_ID", clientID);
Environment.SetEnvironmentVariable("AZURE_TENANT_ID", tenantID);

TokenCredential tokenCredential = new DefaultAzureCredential();

接著,產生的 TokenCredential 可以傳遞給任何接受 Microsoft Entra 認證的 SDK 用戶端的連線至 IoT 中樞 方法:

在此範例中, TokenCredential 會傳遞 至 ServiceClient.Create 以建立 ServiceClient 連接物件。

string hostname = "xxxxxxxxxx.azure-devices.net";
using var serviceClient = ServiceClient.Create(hostname, tokenCredential, TransportType.Amqp);

在此範例中, TokenCredential 會傳遞 至 RegistryManager.Create 以建立 RegistryManager 物件。

string hostname = "xxxxxxxxxx.azure-devices.net";
registryManager = RegistryManager.Create(hostname, tokenCredential);
程式碼範例

如需Microsoft Entra 服務驗證的運作範例,請參閱 角色型驗證範例

建置和傳送此訊息

使用 send_c2d_message 將訊息透過雲端 (IoT 中樞) 傳送至裝置。

send_c2d_message 使用這些參數:

  • deviceID - 目標裝置的字串識別碼。
  • message - 雲端對裝置訊息。 訊息的類型為 str (string)。
  • properties - 類型 dict 的屬性選擇性集合。 屬性可以包含應用程式屬性和系統屬性。 預設值是 {}

此範例會將測試訊息傳送至目標裝置。

# define the device ID
deviceID = "Device-1"

# define the message
message = "{\"c2d test message\"}"

# include optional properties
props={}
props.update(messageId = "message1")
props.update(prop1 = "test property-1")
props.update(prop1 = "test property-2")
prop_text = "Test message"
props.update(testProperty = prop_text)

# send the message through the cloud (IoT Hub) to the device
registry_manager.send_c2d_message(deviceID, message, properties=props)

SDK 傳送訊息範例

適用於 Python 的 Azure IoT SDK 提供服務應用程式的工作範例,示範如何傳送雲端到裝置訊息。 如需詳細資訊,請參閱 send_message.py 示範如何傳送雲端到裝置訊息。

建立裝置應用程式

本節說明如何在適用於 Node.js 的 Azure IoT SDK 中使用 azure-iot-device 套件來接收雲端到裝置訊息。

若要讓 Node.js 型裝置應用程式接收雲端到裝置訊息,必須連線到 IoT 中樞,然後設定來自 IoT 中輸的回呼接聽程式和訊息處理常式來處理傳入訊息。 如果裝置到 IoT 中樞訊息連線中斷,裝置應用程式也應該能夠偵測及處理中斷連線。

安裝 SDK 套件

azure-iot-device 套件 包含與 IoT 裝置互動的物件。 執行此命令,在開發電腦上安裝 azure-iot-device 裝置 SDK:

npm install azure-iot-device --save

將裝置連線到 IoT 中樞

裝置應用程式可以使用下列方法來向 IoT 中樞 進行驗證:

  • X.509 憑證
  • 共用存取金鑰

重要

本文包含使用共用存取簽章 (也稱為對稱金鑰驗證) 連線裝置的步驟。 此驗證方法方便進行測試和評估,但使用 X.509 憑證來驗證裝置是更安全的方法。 若要深入了解,請參閱安全性最佳做法>連線安全性

使用 X.509 憑證進行驗證

X.509 憑證會連結至裝置對 IoT 中樞 連線傳輸。

若要使用 X.509 憑證設定裝置對 IoT 中樞 連線:

  1. 從ConnectionString呼叫 ,將裝置或身分識別模組 連接字串,並將傳輸類型新增至 Client 物件。 將 新增x509=true至 連接字串,表示憑證已新增至 DeviceClientOptions。 例如:

    • 裝置 連接字串:

      HostName=xxxxx.azure-devices.net;DeviceId=Device-1;SharedAccessKey=xxxxxxxxxxxxx;x509=true

    • 身分識別模組 連接字串:

      HostName=xxxxx.azure-devices.net;DeviceId=Device-1;ModuleId=Module-1;SharedAccessKey=xxxxxxxxxxxxx;x509=true

  2. 使用憑證詳細數據設定 JSON 變數,並將其傳遞至 DeviceClientOptions

  3. 呼叫 setOptions 以將 X.509 憑證和密鑰(以及選擇性的複雜密碼)新增至用戶端傳輸。

  4. 呼叫open以從裝置開啟連線至 IoT 中樞。

此範例顯示 JSON 變數內的憑證組態資訊。 認證組態 clientOptions 會傳遞至 setOptions,並使用 開啟 open連線。

const Client = require('azure-iot-device').Client;
const Protocol = require('azure-iot-device-mqtt').Mqtt;
// Connection string illustrated for demonstration only. Never hard-code the connection string in production. Instead use an environmental variable or other secure storage.
const connectionString = `HostName=xxxxx.azure-devices.net;DeviceId=Device-1;SharedAccessKey=xxxxxxxxxxxxx;x509=true`
const client = Client.fromConnectionString(connectionString, Protocol);

var clientOptions = {
   cert: myX509Certificate,
   key: myX509Key,
   passphrase: passphrase,
   http: {
     receivePolicy: {
       interval: 10
     }
   }
 }

 client.setOptions(clientOptions);
 client.open(connectCallback);

如需憑證驗證的詳細資訊,請參閱:

程式碼範例

如需裝置 X.509 憑證驗證的運作範例,請參閱 簡單的範例裝置 X.509

使用共用存取金鑰進行驗證

選擇傳輸通訊協定

Client 物件支援這些通訊協定:

  • Amqp
  • Http - 使用 Http 時,Client 執行個體會不常檢查來自 IoT 中樞的訊息 (至少每25分鐘)。
  • Mqtt
  • MqttWs
  • AmqpWs

在開發電腦上安裝所需的傳輸通訊協定。

例如,此命令會安裝 Amqp 通訊協定:

npm install azure-iot-device-amqp --save

如需 MQTT、AMQP 和 HTTPS 支援之間差異的詳細資訊,請參閱雲端到裝置的通訊指引選擇通訊協定

此範例會將 AMQP 通訊協定指派給 Protocol 變數。 此通訊協定變數會傳遞至本文 新增連接字串 一節中的Client.fromConnectionString 方法。

const Protocol = require('azure-iot-device-mqtt').Amqp;
訊息完成、拒絕和放棄功能

視選擇的通訊協定而定,可以使用訊息完成、拒絕和放棄方法。

AMQP 和 HTTP

AMQP 和 HTTP 傳輸可以完成、拒絕或放棄訊息:

  • 完成 - 若要完成訊息,傳送雲端到裝置訊息的服務會通知已收到訊息。 IoT 中樞會從訊息佇列中移除訊息。 此方法的格式為 client.complete(message, callback function)
  • 拒絕 - 若要拒絕訊息,傳送雲端到裝置訊息的服務會通知裝置未處理訊息。 IoT 中樞會將訊息從裝置佇列中永久移除。 此方法的格式為 client.reject(message, callback function)
  • 放棄 - 若要放棄訊息,IoT 中樞會立即嘗試重新傳送訊息。 IoT 中樞將訊息保留在裝置佇列中以供未來使用。 此方法的格式為 client.abandon(message, callback function)
MQTT

MQTT 不支援訊息完成、拒絕或放棄函數。 相反地,MQTT 預設會接受訊息,並將訊息從 IoT 中樞訊息佇列中移除。

重新傳遞嘗試

如果發生導致裝置無法完成、放棄或拒絕訊息的情況,IoT 中樞在固定的逾時期間之後,會將訊息排入佇列以再次傳遞。 基於這個原因,裝置應用程式中的訊息處理邏輯必須是「等冪」,如此一來,多次接收相同訊息才會產生相同的結果。

建立用戶端物件

使用已安裝的套件建立 Client 物件。

例如:

const Client = require('azure-iot-device').Client;
建立通訊協議物件

使用已安裝的傳輸套件建立 Protocol 物件。

此範例會指派AMQP通訊協定:

const Protocol = require('azure-iot-device-amqp').Amqp;
新增裝置連接字串和傳輸通訊協定

呼叫 fromConnectionString 以提供裝置連線參數:

  • connStr - 裝置 連接字串。
  • transportCtor - 傳輸通訊協定。

此範例會使用 Amqp 傳輸通訊協定:

const deviceConnectionString = "{IoT hub device connection string}"
const Protocol = require('azure-iot-device-mqtt').Amqp;
let client = Client.fromConnectionString(deviceConnectionString, Protocol);

建立傳入訊息處理常式

每個傳入訊息都會呼叫訊息處理常式。

成功接收訊息之後,如果使用 AMQP 或 HTTP 傳輸,請呼叫 client.complete 方法來通知 IoT 中樞,訊息可以從訊息佇列中移除。

例如,此訊息處理常式會將訊息識別碼和訊息本文列印到主控台,然後呼叫 client.complete,通知 IoT 中樞處理訊息,並安全地從裝置佇列中移除該訊息。 如果使用 MQTT 傳輸,則不需要呼叫 complete,而且可以省略。 AMQP 或 HTTPS 傳輸需要呼叫 complete

function messageHandler(msg) {
  console.log('Id: ' + msg.messageId + ' Body: ' + msg.data);
  client.complete(msg, printResultFor('completed'));
}

建立連線中斷連線處理常式

當連線己中斷時會呼叫中斷連線處理常式。 中斷連線處理常式適用於實作重新連線程式碼。

此範例會攔截並顯示主控台的中斷連線錯誤訊息。

function disconnectHandler() {
  clearInterval(sendInterval);
  sendInterval = null;
  client.open().catch((err) => {
    console.error(err.message);
  });
}

新增事件接聽程式

您可以使用 .on 方法來指定這些事件接聽程式。

  • 連線處理常式
  • 錯誤處理常式
  • 中斷連線處理常式
  • 訊息處理常式

此範例包含先前定義的訊息和中斷連線處理常式。

client.on('connect', connectHandler);
client.on('error', errorHandler);
client.on('disconnect', disconnectHandler);
client.on('message', messageHandler);

開啟連線到 IoT 中樞

使用 open 方法來開啟 IoT 裝置與 IoT 中樞之間的連線。 使用 .catch(err) 來攔截錯誤並呼叫處理常式程式碼。

例如:

client.open()
.catch((err) => {
  console.error('Could not connect: ' + err.message);
});

SDK 裝置範例

適用於 Node.js的 Azure IoT SDK 提供處理訊息接收之裝置應用程式的工作範例。 如需詳細資訊,請參閱

simple_sample_device - 會連線到 IoT 中樞,並接收雲端到裝置應用程式訊息。

建立後端應用程式

本節說明如何傳送雲端到裝置的訊息。 如先前所述,解決方案後端應用程式會連線到 IoT 中樞,並將訊息傳送至使用目的地裝置編碼的 IoT 中樞。 IoT 中樞會將傳入訊息儲存至其訊息佇列,而訊息會從 IoT 中樞訊息佇列傳遞至目標裝置。

解決方案後端應用程式也可以針對傳送至 IoT 中樞的訊息,要求並接收傳遞意見反應,該訊息會透過訊息佇列傳送裝置。

安裝服務 SDK 套件

azure-iothub 套件包含與 IoT 中樞互動的物件。 本文說明 Client 類別程式碼,這些程式碼會透過 IoT 中樞將訊息從應用程式傳送至裝置。

執行此命令,在開發電腦上安裝 azure-iothub

npm install azure-iothub --save

載入用戶端和訊息模組

使用來自 azure-iothub 封裝的 Client 類別宣告 Client 物件。

使用來自 azure-iot-common 封裝的 Message 類別宣告 Message 物件。

'use strict';
var Client = require('azure-iothub').Client;
var Message = require('azure-iot-common').Message;

連線至 IoT 中樞

您可以使用下列方法,將後端服務連線到 IoT 中樞:

  • 共用存取原則
  • Microsoft Entra

重要

本文包含使用共用存取簽章連線至服務的步驟。 此驗證方法方便進行測試和評估,但使用 Microsoft Entra ID 或受控識別向服務進行驗證是更安全的方法。 若要深入了解,請參閱安全性最佳做法 > 雲端安全性

使用共用存取原則進行連線

使用 fromConnectionString 連線到 IoT 中樞。

在此範例中,會使用 Amqp 傳輸類型建立 serviceClient 物件。

var connectionString = '{IoT hub device connection string}';
var serviceClient = Client.fromConnectionString(connectionString,`Amqp`);
開啟用戶端連線

呼叫 Client open 方法來開啟應用程式與 IoT 中樞之間的連線。

可以搭配 open 或呼叫,而不指定 open 作業完成時所呼叫的回呼函數。

在此範例中,open 方法包含選擇性 err 開啟的連線回呼函數。 如果發生開啟錯誤,則會傳回錯誤物件。 如果開啟的連接成功,則會傳回 null 回呼值。

serviceClient.open(function (err)
if (err)
  console.error('Could not connect: ' + err.message);

使用 Microsoft Entra 進行連線

使用 Microsoft Entra 的後端應用程式必須先成功驗證並取得安全性令牌認證,才能連線到 IoT 中樞。 此令牌會傳遞至 IoT 中樞 連接方法。 如需設定和使用 Microsoft Entra 進行 IoT 中樞 的一般資訊,請參閱使用 Microsoft Entra ID 控制對 IoT 中樞 的存取。

如需Node.js SDK 驗證的概觀,請參閱:

設定 Microsoft Entra 應用程式

您必須設定已針對您慣用的驗證認證設定Microsoft Entra 應用程式。 應用程式包含參數,例如後端應用程式用來驗證的客戶端密碼。 可用的應用程式驗證群組態如下:

  • 用戶端密碼
  • [MSSQLSERVER 的通訊協定內容]
  • 同盟身分識別認證

Microsoft Entra 應用程式可能需要特定角色許可權,視執行的作業而定。 例如,需要 IoT 中樞 對應項參與者,才能啟用 IoT 中樞 裝置和模塊對應項的讀取和寫入存取權。 如需詳細資訊,請參閱使用 Azure RBAC 角色指派來管理 IoT 中樞 的存取權。

如需設定 Microsoft Entra 應用程式的詳細資訊,請參閱快速入門:使用 Microsoft 身分識別平台 註冊應用程式。

使用 DefaultAzureCredential 進行驗證

使用 Microsoft Entra 來驗證後端應用程式最簡單的方式是使用 DefaultAzureCredential,但建議在生產環境中使用不同的方法,包括特定TokenCredential或剖析。ChainedTokenCredential 為了簡單起見,本節說明使用 DefaultAzureCredential 和用戶端密碼的驗證。 如需使用 DefaultAzureCredential之優缺點的詳細資訊,請參閱 適用於 JavaScript 的 Azure 身分識別客戶端連結庫中的認證鏈結。

DefaultAzureCredential 支援不同的驗證機制,並根據執行中的環境來判斷適當的認證類型。 它會嘗試依序使用多個認證類型,直到找到有效的認證為止。

Microsoft Entra 需要此套件:

npm install --save @azure/identity

在此範例中,Microsoft Entra 應用程式註冊客戶端密碼、用戶端標識碼和租使用者標識碼已新增至環境變數。 這些環境變數是用來 DefaultAzureCredential 驗證應用程式。 成功Microsoft Entra 驗證的結果是傳遞至 IoT 中樞 連線方法的安全性令牌認證。

import { DefaultAzureCredential } from "@azure/identity";

// Azure SDK clients accept the credential as a parameter
const credential = new DefaultAzureCredential();

接著,產生的認證令牌可以傳遞至fromTokenCredential,以連線到接受 Microsoft Entra 認證的任何 SDK 用戶端 IoT 中樞:

fromTokenCredential 需要兩個參數:

  • Azure 服務 URL - Azure 服務 URL 的格式 {Your Entra domain URL}.azure-devices.net 應該不含 https:// 前置詞。 例如: MyAzureDomain.azure-devices.net
  • Azure 認證令牌

在此範例中,會使用 DefaultAzureCredential取得 Azure 認證。 接著會提供 Azure 網域 URL 和認證,Registry.fromTokenCredential以建立 IoT 中樞 的連線。

const { DefaultAzureCredential } = require("@azure/identity");

let Registry = require('azure-iothub').Registry;

// Define the client secret values
clientSecretValue = 'xxxxxxxxxxxxxxx'
clientID = 'xxxxxxxxxxxxxx'
tenantID = 'xxxxxxxxxxxxx'

// Set environment variables
process.env['AZURE_CLIENT_SECRET'] = clientSecretValue;
process.env['AZURE_CLIENT_ID'] = clientID;
process.env['AZURE_TENANT_ID'] = tenantID;

// Acquire a credential object
const credential = new DefaultAzureCredential()

// Create an instance of the IoTHub registry
hostName = 'MyAzureDomain.azure-devices.net';
let registry = Registry.fromTokenCredential(hostName,credential);
程式碼範例

如需Microsoft Entra 服務驗證的工作範例,請參閱 Azure 身分識別範例

建立一則訊息

訊息物件包含非同步的雲端到裝置訊息。 訊息功能在 AMQP、MQTT 和 HTTP 上的運作方式相同。

訊息物件支持數個屬性,包括這些屬性。 如需完整清單,請參閱 message 屬性。

  • ack - 傳遞意見反應。 於下一節說明。
  • properties - 對應包含用來儲存自定義訊息屬性的字串索引鍵和值。
  • messageId - 用來關聯雙向通訊。

在具現化訊息物件時新增郵件內文。 在此範例中,會新增 'Cloud to device message.' 訊息。

var message = new Message('Cloud to device message.');
message.ack = 'full';
message.messageId = "My Message ID";

傳遞通知

傳送程式可向 IoT 中樞要求每個雲端到裝置訊息的傳遞 (或到期) 通知。 此動作可讓傳送程式使用通知、重試或補償邏輯。 訊息意見反應作業和屬性的完整描述會在訊息意見反應描述。

用來接收訊息意見反應的每個訊息,都必須包含傳遞通知的值,Ack 屬性。 ack 屬性可以是下列值之一:

  • none (預設值):不會產生任何意見反應訊息。

  • sent:如果訊息已完成,則接收意見反應訊息。

  • :如果訊息已過期 (或達到最大傳遞計數),則接收意見反應訊息,而不會由裝置完成。

  • full:已傳送和未傳送結果的意見反應。

在本範例中,ack 屬性設為 full,針對一個訊息要求傳遞和未傳遞的訊息傳遞意見反應。

message.ack = 'full';

訊息意見反應接收者回呼函數會使用 getFeedbackReceiver 連結到 Client

訊息意見反應接收者會收到兩個自變數:

  • Error 物件 (可以是 Null)
  • AmqpReceiver 物件 - 用戶端收到新的意見反應訊息時發出事件。

此範例函數會接收並列印傳遞意見反應訊息至主控台。

function receiveFeedback(err, receiver){
  receiver.on('message', function (msg) {
    console.log('Feedback message:')
    console.log(msg.getData().toString('utf-8'));
  });
}

此程式碼會使用 getFeedbackReceiver,將 receiveFeedback 意見反應回呼函數連結至服務 Client 物件。

serviceClient.getFeedbackReceiver(receiveFeedback);

定義訊息完成結果處理程式

訊息傳送完成回呼函數會在傳送每個訊息之後呼叫。

此範例函數會將訊息 send 作業結果列印至主控台。 在此範例中,printResultFor 函數會以參數的形式提供給下一節所述的 send 函數。

function printResultFor(op) {
  return function printResult(err, res) {
    if (err) console.log(op + ' error: ' + err.toString());
    if (res) console.log(op + ' status: ' + res.constructor.name);
  };
}

傳送訊息

使用 send 函數,透過 IoT 中樞將非同步雲端到裝置訊息傳送至裝置應用程式。

send 支援列出這些參數:

  • deviceID - 目標裝置的裝置識別碼。
  • message - 要傳送到裝置的訊息本文。
  • done - 作業完成時要呼叫的選擇性函數。 完成會使用兩個自變數來呼叫:
    • Error 物件 (可以是 Null)。
    • 傳輸特定回應物件適用於記錄或偵錯。

此程式碼會呼叫 send,透過 IoT 中樞將雲端到裝置訊息傳送至裝置應用程式。 上一節中定義的回呼函數 printResultFor 會收到傳遞通知資訊。

var targetDevice = '{device ID}';
serviceClient.send(targetDevice, message, printResultFor('send'));

本範例是當裝置收到雲端到裝置訊息時,會如何將訊息傳送至您的裝置,並處理意見反應訊息:

serviceClient.open(function (err) {
  if (err) {
    console.error('Could not connect: ' + err.message);
  } else {
    console.log('Service client connected');
    serviceClient.getFeedbackReceiver(receiveFeedback);
    var message = new Message('Cloud to device message.');
    message.ack = 'full';
    message.messageId = "My Message ID";
    console.log('Sending message: ' + message.getData());
    serviceClient.send(targetDevice, message, printResultFor('send'));
  }
});

SDK 傳送訊息範例

適用於 Node.js的 Azure IoT SDK 提供處理傳送訊息工作之服務應用程式的工作範例。 如需詳細資訊,請參閱

send_c2d_message.js - 透過 IoT 中樞將 C2D 訊息傳送至裝置。

連線重新連線原則

本文不會示範裝置對 IoT 中樞連線或 IoT 中樞連線外部應用程式的訊息重試原則。 在生產程式碼中,您應該實作連線重試原則,如管理裝置重新連線,以建立具復原性的應用程式

訊息保留時間、重試嘗試和最大傳遞計數

從 IoT 中樞傳送雲端到裝置訊息中所述,您可以使用入口網站 IoT 中樞設定選項或 Azure CLI 來檢視及設定下列訊息值的預設值。 這些設定選項可能會影響訊息傳遞和意見反應。

  • 預設 TTL (存留時間) - 在 IoT 中樞停用訊息之前,裝置可取用訊息的時間長度。
  • 意見反應保留時間 - IoT 中樞保留意見反應的時間量,以取得雲端到裝置訊息的到期或傳遞。
  • IoT 中樞嘗試將雲端到裝置的訊息傳遞到裝置的次數。