ジョブのスケジュールとブロードキャスト (.NET)

Azure IoT Hub を使用して、数百万のデバイスを更新するジョブのスケジュールと追跡を行います。 ジョブを使用して、次の操作を行います。

  • 必要なプロパティを更新する

  • タグを更新する

  • ダイレクト メソッドを呼び出す

ジョブはこれらのアクションの 1 つをラップし、デバイス ツイン クエリで定義されるデバイスのセットに対して実行状況を追跡します。 たとえば、バックエンド アプリは、ジョブを使用して 10,000 台のデバイスでダイレクト メソッドを呼び出し、デバイスを再起動できます。 デバイス ツイン クエリでデバイスのセットを指定し、ジョブが将来実行されるようにスケジュールを設定します。 各デバイスが reboot ダイレクト メソッドを受信し、実行するたびに、ジョブは進行状況を追跡します。

これらの各機能の詳細については、次の記事をご覧ください。

Note

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

この記事では、次の 2 つの .NET (C#) コンソール アプリを作成する方法について説明します。

  • バックエンド アプリから呼び出すことができる LockDoor というダイレクト メソッドを実装するデバイス アプリ SimulateDeviceMethods

  • 2 つのジョブを作成するバックエンド アプリ ScheduleJob。 1 つのジョブが lockDoor ダイレクト メソッドを呼び出し、別のジョブが必要なプロパティの更新を複数のデバイスに送信します。

注意

デバイスとバックエンド アプリの両方の構築に使用できる SDK ツールに関する詳細については、「Azure IoT Hub SDK」を参照してください。

前提条件

  • 見ることができます。

  • IoT Hub。 CLI または Azure portal を使って作成します。

  • 登録済みのデバイス。 Azure portal に登録してください。

  • ポート 8883 がファイアウォールで開放されていることを確認してください。 この記事のデバイス サンプルでは、ポート 8883 を介して通信する MQTT プロトコルを使用しています。 このポートは、企業や教育用のネットワーク環境によってはブロックされている場合があります。 この問題の詳細と対処方法については、「IoT Hub への接続 (MQTT)」を参照してください。

シミュレート対象デバイス アプリの作成

このセクションでは、ソリューション バックエンドによって呼び出されたダイレクト メソッドに応答する .NET コンソール アプリを作成します。

  1. Visual Studio で、 [新しいプロジェクトの作成] を選択し、 [コンソール アプリ (.NET Framework)] プロジェクト テンプレートを選択します。 [次へ] をクリックして続行します。

  2. [新しいプロジェクトの構成] で、プロジェクトに SimulateDeviceMethods という名前を付け、[次へ] を選びます。

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

  3. .NET Framework の既定のバージョンをそのまま使い、[作成] を選んでプロジェクトを作成します。

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

  5. [NuGet パッケージ マネージャー][参照] を選択し、Microsoft.Azure.Devices.Client を検索して選択します。 [インストール] を選択します。

    Visual Studio の NuGet パッケージ マネージャーのスクリーンショット。

    この手順により、パッケージのダウンロードとインストールが実行され、Azure IoT device SDK NuGet パッケージへの参照とその依存関係が追加されます。

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

    using Microsoft.Azure.Devices.Client;
    using Microsoft.Azure.Devices.Shared;
    using Newtonsoft.Json;
    using System.Threading.Tasks;
    using System.Text;
    
  7. Program クラスに次のフィールドを追加します。 プレースホルダーの値は、前のセクションで記したデバイス接続文字列に置き換えてください。

    static string DeviceConnectionString = "<yourDeviceConnectionString>";
    static DeviceClient Client = null;
    
  8. 次のコードを追加して、デバイスにダイレクト メソッドを実装します。

    static Task<MethodResponse> LockDoor(MethodRequest methodRequest, object userContext)
    {
        Console.WriteLine();
        Console.WriteLine("Locking Door!");
        Console.WriteLine("\nReturning response for method {0}", methodRequest.Name);
    
        string result = "'Door was locked.'";
        return Task.FromResult(new MethodResponse(Encoding.UTF8.GetBytes(result), 200));
    }
    
  9. 次のメソッドを追加して、デバイスにデバイス ツイン リスナーを実装します。

    private static async Task OnDesiredPropertyChanged(TwinCollection desiredProperties, 
      object userContext)
    {
        Console.WriteLine("Desired property change:");
        Console.WriteLine(JsonConvert.SerializeObject(desiredProperties));
    }
    
  10. 最後に、IoT ハブへの接続を開いてメソッド リスナーを初期化する次のコードを Main メソッドに追加します。

    try
    {
        Console.WriteLine("Connecting to hub");
        Client = DeviceClient.CreateFromConnectionString(DeviceConnectionString, 
          TransportType.Mqtt);
    
        Client.SetMethodHandlerAsync("LockDoor", LockDoor, null);
        Client.SetDesiredPropertyUpdateCallbackAsync(OnDesiredPropertyChanged, null);
    
        Console.WriteLine("Waiting for direct method call and device twin update\n Press enter to exit.");
        Console.ReadLine();
    
        Console.WriteLine("Exiting...");
    
        Client.SetMethodHandlerAsync("LockDoor", null, null);
        Client.CloseAsync().Wait();
    }
    catch (Exception ex)
    {
        Console.WriteLine();
        Console.WriteLine("Error in sample: {0}", ex.Message);
    }
    
  11. 作業内容を保存し、ソリューションを構築します。

注意

わかりやすくするために、この記事では再試行ポリシーは実装しません。 運用環境のコードには、「一時的な障害の処理」で推奨されているように、再試行ポリシー (接続の再試行など) を実装する必要があります。

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

この記事では、デバイス上で直接メソッドを呼び出すようにジョブをスケジュールし、デバイス ツインを更新するようにジョブをスケジュールし、各ジョブの進行状況を監視するバックエンド サービスを作成します。 これらの操作を実行するには、サービスにレジストリ読み取りおよびレジストリ書き込みのアクセス許可が必要です。 既定では、すべての IoT ハブは、これらのアクセス許可を付与する registryReadWrite という名前の共有アクセス ポリシーがある状態で作成されます。

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

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

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

  3. ポリシーの一覧から、 [registryReadWrite] ポリシーを選択します。

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

    接続文字列を取得する方法を示すスクリーン キャプチャ

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

ダイレクト メソッドを呼び出し、デバイス ツインの更新を送信するジョブのスケジュール

このセクションでは、ジョブを使用して LockDoor ダイレクト メソッドを呼び出し、複数のデバイスに必要なプロパティの更新を送信する .NET コンソール アプリ (C# を使用) を作成します。

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

  2. [新しいプロジェクトの構成] で、プロジェクトに ScheduleJob という名前を付け [作成] を選びます。

    ScheduleJob プロジェクトに名前を付けて構成する

    Visual Studio の [新しいプロジェクトの構成] ポップアップで名前を追加するスクリーンショット。

  3. .NET Framework の既定のバージョンをそのまま使い、[作成] を選んでプロジェクトを作成します。

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

  5. [NuGet パッケージ マネージャー][参照] を選択し、Microsoft.Azure.Devices を検索して選択してから、 [インストール] を選択します。

    この手順により、パッケージのダウンロードとインストールが実行され、Azure IoT service SDK NuGet パッケージへの参照とその依存関係が追加されます。

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

    using Microsoft.Azure.Devices;
    using Microsoft.Azure.Devices.Shared;
    
  7. 既定のステートメント内に存在しない場合は、次の using ステートメントを追加します。

    using System.Threading;
    using System.Threading.Tasks;
    
  8. Program クラスに次のフィールドを追加します。 プレースホルダーを前述の「IoT ハブ接続文字列を取得する」でコピーした IoT Hub 接続文字列とデバイスの名前に置き換えます。

    static JobClient jobClient;
    static string connString = "<yourIotHubConnectionString>";
    static string deviceId = "<yourDeviceId>";
    
  9. Program クラスに次のメソッドを追加します。

    public static async Task MonitorJob(string jobId)
    {
        JobResponse result;
        do
        {
            result = await jobClient.GetJobAsync(jobId);
            Console.WriteLine("Job Status : " + result.Status.ToString());
            Thread.Sleep(2000);
        } while ((result.Status != JobStatus.Completed) && 
          (result.Status != JobStatus.Failed));
    }
    
  10. Program クラスに次のメソッドを追加します。

    public static async Task StartMethodJob(string jobId)
    {
        CloudToDeviceMethod directMethod = 
          new CloudToDeviceMethod("LockDoor", TimeSpan.FromSeconds(5), 
          TimeSpan.FromSeconds(5));
    
        JobResponse result = await jobClient.ScheduleDeviceMethodAsync(jobId,
            $"DeviceId IN ['{deviceId}']",
            directMethod,
            DateTime.UtcNow,
            (long)TimeSpan.FromMinutes(2).TotalSeconds);
    
        Console.WriteLine("Started Method Job");
    }
    
  11. 別のメソッドを Program クラスに追加します。

    public static async Task StartTwinUpdateJob(string jobId)
    {
        Twin twin = new Twin(deviceId);
        twin.Tags = new TwinCollection();
        twin.Tags["Building"] = "43";
        twin.Tags["Floor"] = "3";
        twin.ETag = "*";
    
        twin.Properties.Desired["LocationUpdate"] = DateTime.UtcNow;
    
        JobResponse createJobResponse = jobClient.ScheduleTwinUpdateAsync(
            jobId,
            $"DeviceId IN ['{deviceId}']", 
            twin, 
            DateTime.UtcNow, 
            (long)TimeSpan.FromMinutes(2).TotalSeconds).Result;
    
        Console.WriteLine("Started Twin Update Job");
    }
    

    注意

    クエリ構文の詳細については、IoT Hub クエリ言語に関するページを参照してください。

  12. 最後に、Main メソッドに次の行を追加します。

    Console.WriteLine("Press ENTER to start running jobs.");
    Console.ReadLine();
    
    jobClient = JobClient.CreateFromConnectionString(connString);
    
    string methodJobId = Guid.NewGuid().ToString();
    
    StartMethodJob(methodJobId);
    MonitorJob(methodJobId).Wait();
    Console.WriteLine("Press ENTER to run the next job.");
    Console.ReadLine();
    
    string twinUpdateJobId = Guid.NewGuid().ToString();
    
    StartTwinUpdateJob(twinUpdateJobId);
    MonitorJob(twinUpdateJobId).Wait();
    Console.WriteLine("Press ENTER to exit.");
    Console.ReadLine();
    
  13. 作業内容を保存し、ソリューションを構築します。

アプリの実行

これで、アプリを実行する準備が整いました。

  1. Visual Studio ソリューション エクスプローラーでソリューションを右クリックし、 [スタートアップ プロジェクトの設定] を選択します。

  2. [共通プロパティ]>[スタートアップ プロジェクト] の順に選択し、 [マルチ スタートアップ プロジェクト] を選択します。

  3. SimulateDeviceMethods が一覧の一番上にあり、その後に ScheduleJob があることを確認します。 両方のアクションを [開始] に設定し、 [OK] を選択します。

  4. [開始] をクリックしてプロジェクトを実行するか、 [デバッグ] メニューに移動し、 [デバッグの開始] をクリックします。

    デバイスとバックエンド アプリの両方からの出力が表示されます。

    アプリを実行して、ジョブをスケジュールします。

次の手順

この記事では、ダイレクト メソッドを実行してデバイス ツインのプロパティを更新するようにジョブをスケジュールしました。

IoT Hub とデバイス管理パターンの調査を続けるには、「Raspberry Pi 3 B+ 参照イメージを使用した Device Update for Azure IoT Hub のチュートリアル」でイメージを更新してください。