IoT Hub (.NET) を使用したクラウドからデバイスへのメッセージの送信

Azure IoT Hub は、何百万ものデバイスとソリューション バックエンドの間に信頼性のある保護された双方向通信を確立するのに役立つ、フル マネージドのサービスです。

この記事で取り上げるテクニック:

  • ソリューション バックエンドから IoT Hub 経由で単一のデバイスに cloud-to-device (C2D) メッセージを送信する

  • cloud-to-device メッセージをデバイスで受信する

  • ソリューション バックエンドから、IoT Hub からデバイスに送信されたメッセージの配信確認 ("フィードバック") を要求する

注意

この記事で説明されている機能は、Standard レベルの IoT Hub でのみ使用できます。 Basic および Standard または Free レベルの IoT Hub の詳細については、ソリューションに適した IoT Hub のレベルの選択に関するページを参照してください。

この記事の最後に、次の 2 つの .NET コンソール アプリを実行します。

  • MessageReceiveSample: Microsoft Azure IoT SDK for .NET に含まれているサンプル デバイス アプリ。これは、IoT ハブに接続し、cloud-to-device メッセージを受信します。

  • SendCloudToDevice: IoT Hub 経由で cloud-to-device メッセージをデバイス アプリに送信し、その配信確認を受信します。

注意

IoT Hub には、Azure IoT device SDK を介して、多数のデバイス プラットフォームと言語 (C、Java、Python、JavaScript) に対する SDK サポートがあります。

cloud-to-device メッセージの詳細については、IoT Hub における D2C と C2D のメッセージングに関するページを参照してください。

前提条件

  • Azure サブスクリプション。 Azure サブスクリプションをお持ちでない場合は、開始する前に 無料アカウント を作成してください。

  • Azure サブスクリプション内の IoT ハブ。 ハブがまだない場合は、「IoT ハブの作成」の手順に従うことができます。

  • お使いの IoT ハブに登録されているデバイス。 デバイスをまだ登録していない場合は、Azure portal に登録します。

  • この記事では、C# 向けの Azure IoT SDK のサンプル コードを使用します。

    • GitHub から開発用マシンに SDK リポジトリをダウンロードするか、複製します。
    • 開発用マシンに .NET Core 3.0.0 以上がインストールされていることを確認します。 dotnet --version を実行してバージョンを確認し、必要に応じて .NET をダウンロードします。
  • ポート 8883 がファイアウォールで開放されていることを確認してください。 この記事のデバイス サンプルでは、ポート 8883 を介して通信する MQTT プロトコルを使用しています。 このポートは、企業や教育用のネットワーク環境によってはブロックされている場合があります。 この問題の詳細と対処方法については、「IoT Hub への接続 (MQTT)」を参照してください。

  • 見ることができます。

デバイスの接続文字列を取得する

この記事では、デバイスをシミュレートするサンプル アプリを実行します。これは、IoT Hub 経由で送信された cloud-to-device メッセージを受信します。 Microsoft Azure IoT SDK for .NET に含まれる MessageReceiveSample サンプル アプリは、IoT ハブに接続し、シミュレートされたデバイスとして動作します。 このサンプルは、IoT ハブに登録されているデバイスのプライマリ接続文字列を使用します。

IoT ハブに登録されているデバイスのプライマリ接続文字列を取得するには、次の手順に従います。

  1. Azure portal で、 [リソース グループ] を選択します。 ハブが配置されているリソース グループを選択し、リソースの一覧からハブを選択します。

  2. IoT ハブの左側ペインの [デバイス管理] の下にある [デバイス] を選択します。

  3. デバイスの一覧から、該当するデバイスを選択します。

  4. [プライマリ接続文字列] をコピーし、値を保存します。

    Azure portal で IoT ハブに登録されているデバイスからプライマリ接続文字列を取得する方法を示すスクリーンショット。

デバイス アプリでメッセージを受信する

このセクションでは、MessageReceiveSample サンプル デバイス アプリを実行して、IoT ハブ経由で送信された C2D メッセージを受信します。 新しいコマンド プロンプトを開き、Azure IoT C# SDK を解凍したフォルダーの下の azure-iot-sdk-csharp\iothub\device\samples\getting started\MessageReceiveSample フォルダーに移動します。 {Your device connection string} プレースホルダーの値を IoT ハブに登録されているデバイスからコピーしたデバイス接続文字列に置き換えて、次のコマンドを実行します。

dotnet restore
dotnet run --c "{Your device connection string}"

サンプル デバイス アプリが正常に起動して IoT ハブに接続すると、次のように出力されます。

5/22/2023 11:13:18 AM> Press Control+C at any time to quit the sample.
     
5/22/2023 11:13:18 AM> Device waiting for C2D messages from the hub...
5/22/2023 11:13:18 AM> Use the Azure Portal IoT hub blade or Azure IoT Explorer to send a message to this device.
5/22/2023 11:13:18 AM> Trying to receive C2D messages by polling using the ReceiveAsync() method. Press 'n' to move to the next phase.

サンプル デバイス アプリは、ReceiveAsyncCompleteAsync メソッドを使用してメッセージをポーリングします。 ReceiveC2dMessagesPollingAndCompleteAsync メソッドは ReceiveAsync メソッドを使用します。これは、デバイスがメッセージを受信した時点で受信したメッセージを非同期的に返します。 ReceiveAsync は、指定可能タイムアウト期間を過ぎると "null" を返します。 この例では、既定の 1 分が使用されます。 デバイスは、"null" を受信すると新しいメッセージを待機し続ける必要があります。 サンプル アプリの ReceiveC2dMessagesPollingAndCompleteAsync メソッドに次のコード ブロックが含まれているのは、この要件のためです。

   if (receivedMessage == null)
   {
      continue;
   }

CompleteAsync メソッドの呼び出しは、メッセージが正常に処理されたこと、およびメッセージをデバイスのキューから安全に削除できることを IoT Hub に通知します。 デバイスは、使用しているプロトコルに関係なく、処理が正常に完了したときに、このメソッドを呼び出す必要があります。

MQTT プロトコルではできませんが、AMQP および HTTPS プロトコルでは、デバイスは次のこともできます。

  • メッセージを破棄します。この場合、IoT Hub は将来の使用に備えてメッセージをデバイスのキュー内に保持します。
  • メッセージを拒否します。この場合、メッセージはデバイスのキューから完全に削除されます。

デバイスがメッセージを完了、破棄、または拒否することを妨げる問題が発生した場合、IoT Hub は一定のタイムアウト期間が経過した後で、メッセージの配信をキューに入れます。 このような理由から、同じメッセージを複数回受信した場合に生成される結果が毎回同じになるように、デバイス アプリ内のメッセージ処理ロジックをべき等にする必要があります。

cloud-to-device メッセージのライフサイクルと、IoT Hub が cloud-to-device メッセージを処理する方法の詳細については、「IoT ハブから cloud-to-device メッセージを送信する」を参照してください。

注意

トランスポートとして MQTT や AMQP ではなく HTTPS を使用している場合、ReceiveAsync メソッドは即時に返されます。 HTTPS を使用するクラウドからデバイスへのメッセージに関してサポートされているパターンは、メッセージを低頻度 (最小 25 分の間隔) でチェックするデバイスに断続的に接続されます。 HTTPS 受信の発行が多くなれば、IoT Hub で要求が調整されます。 MQTT、AMQP、および HTTPS のサポートの相違点の詳細については、「cloud-to-device 通信に関するガイダンス」と「通信プロトコルの選択」を参照してください。

IoT ハブ接続文字列を取得する

この記事では、IoT Hub を介して cloud-to-device メッセージを送信するバックエンド サービスを作成します。 cloud-to-device メッセージを送信するサービスには、サービス接続のアクセス許可が必要となります。 既定では、どの IoT Hub も、このアクセス許可を付与する service という名前の共有アクセス ポリシーがある状態で作成されます。

サービス ポリシーの IoT Hub 接続文字列を取得するには、次の手順を実行します。

  1. Azure portal で、 [リソース グループ] を選択します。 ハブが配置されているリソース グループを選択し、リソースの一覧からハブを選択します。

  2. IoT ハブの左側のウィンドウで、 [共有アクセス ポリシー] を選択します。

  3. ポリシーの一覧から、サービス ポリシーを選択します。

  4. [プライマリ接続文字列] をコピーし、値を保存します。

Azure portal で IoT ハブから接続文字列を取得する方法を示すスクリーンショット。

IoT Hub の共有アクセス ポリシーとアクセス許可の詳細については、「アクセス制御とアクセス許可」を参照してください。

C2D メッセージを送信する

このセクションでは、クラウドからデバイスへのメッセージを、シミュレートされたデバイス アプリに送信する .NET コンソール アプリを作成します。 デバイスからのデバイス ID と IoT ハブの接続文字列が必要です。

  1. Visual Studio で、 [ファイル]>[新規]>[プロジェクト] の順に選択します。 [新しいプロジェクトの作成] で、 [コンソール アプリ (.NET Framework)] を選択してから、 [次へ] を選択します。

  2. プロジェクトに SendCloudToDevice という名前を付けて、[次へ] を選択します。

    Visual Studio の [新しいプロジェクトの構成] ポップアップのスクリーンショット。

  3. .NET Framework の最新バージョンを受け入れます。 [作成] を選択してプロジェクトを作成します。

  4. ソリューション エクスプローラーで、新しいプロジェクトを右クリックし、 [NuGet パッケージの管理] を選択します。

  5. [NuGet パッケージの管理] ウィンドウで [参照] を選択し、Microsoft.Azure.Devices を検索して選択します。 [インストール] を選択します。

    この手順により Azure IoT サービス SDK NuGet パッケージがダウンロードされ、インストールされ、パッケージへの参照が追加されます。

  6. Program.cs ファイルの先頭に次の using ステートメントを追加します。

    using Microsoft.Azure.Devices;
    
  7. Program クラスに次のフィールドを追加します。 {iot hub connection string} プレースホルダーの値を、先ほど「IoT ハブ接続文字列を取得する」で書き留めた IoT Hub 接続文字列に置き換えます。 {device id} プレースホルダーの値を、IoT ハブに登録されているデバイスのデバイス ID に置き換えます。

    static ServiceClient serviceClient;
    static string connectionString = "{iot hub connection string}";
    static string targetDevice = "{device id}";
    
  8. メッセージをデバイスに送信するために、次のメソッドを Program クラスに追加します。

    private async static Task SendCloudToDeviceMessageAsync()
    {
         var commandMessage = new
          Message(Encoding.ASCII.GetBytes("Cloud to device message."));
         await serviceClient.SendAsync(targetDevice, commandMessage);
    }
    
  9. 最後に、 Main メソッドに次の行を追加します。

    Console.WriteLine("Send Cloud-to-Device message\n");
    serviceClient = ServiceClient.CreateFromConnectionString(connectionString);
    
    Console.WriteLine("Press any key to send a C2D message.");
    Console.ReadLine();
    SendCloudToDeviceMessageAsync().Wait();
    Console.ReadLine();
    
  10. F5 キーを押してサンプル サービス アプリを起動します。 [SendCloudToDevice] ウィンドウを選択して Enter キーを押します。 次の出力例に示すように、サンプル デバイス アプリによって受信されたメッセージが表示されます。

    5/22/2023 11:13:18 AM> Press Control+C at any time to quit the sample.
    
    5/22/2023 11:13:18 AM> Device waiting for C2D messages from the hub...
    5/22/2023 11:13:18 AM> Use the Azure Portal IoT hub blade or Azure IoT Explorer to send a message to this device.
    5/22/2023 11:13:18 AM> Trying to receive C2D messages by polling using the ReceiveAsync() method. Press 'n' to move to the next phase.
    5/22/2023 11:15:18 AM> Polling using ReceiveAsync() - received message with Id=
    5/22/2023 11:15:18 AM> Received message: [Cloud to device message.]
            Content type:
    
    5/22/2023 11:15:18 AM> Completed C2D message with Id=.
    

配信フィードバックの受信

各 cloud-to-device メッセージに対して IoT Hub からの配信 (または有効期限) 確認を要求することができます。 このオプションにより、ソリューションのバックエンドで通知、再試行、または補正ロジックを簡単に実行できます。 cloud-to-device フィードバックの詳細については、IoT Hub における D2C と C2D のメッセージングに関するページを参照してください。

このセクションでは、フィードバックを要求し、それを IoT ハブから受信するように、SendCloudToDevice サンプル サービス アプリを変更します。

  1. Visual Studio の SendCloudToDevice プロジェクトで、次のメソッドを Program クラスに追加します。

    private async static void ReceiveFeedbackAsync()
    {
         var feedbackReceiver = serviceClient.GetFeedbackReceiver();
    
         Console.WriteLine("\nReceiving c2d feedback from service");
         while (true)
         {
             var feedbackBatch = await feedbackReceiver.ReceiveAsync();
             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);
         }
     }
    

    この受信パターンは、クラウドからデバイスへのメッセージをデバイス アプリから受信するために使用するものと同じであることに注意してください。

  2. Main メソッドの serviceClient = ServiceClient.CreateFromConnectionString(connectionString) の直後に次の行を追加します。

    ReceiveFeedbackAsync();
    
  3. クラウドからデバイスへのメッセージの配信に対するフィードバックを要求するには、SendCloudToDeviceMessageAsync メソッドでプロパティを指定する必要があります。 var commandMessage = new Message(...); 行の直後に次の行を追加します。

    commandMessage.Ack = DeliveryAcknowledgement.Full;
    
  4. サンプル デバイス アプリが実行されていることを確認し、F5 キーを押してサンプル サービス アプリを実行します。 [SendCloudToDevice] コンソール ウィンドウを選択して Enter キーを押します。 サンプル デバイス アプリがメッセージを受信し、その数秒後に、SendCloudToDevice アプリケーションによるフィードバック メッセージの受信が表示されます。 次の出力は、サンプル サービス アプリによって受信されたフィードバック メッセージを示しています。

    Send Cloud-to-Device message
    
    
    Receiving c2d feedback from service
    Press any key to send a C2D message.
    
    Received feedback: Success
    

注意

わかりやすくするために、この記事では再試行ポリシーは実装しません。 運用コードでは、「一時的な障害の処理」で推奨されているように、再試行ポリシー (エクスポネンシャル バックオフなど) を実装してください。

次のステップ

この記事では、クラウドからデバイスへのメッセージを送受信する方法を学習しました。