Skip to main content

使用Schedule job对多个设备进行操作

分类:  Azure物联网 标签:  #Azure # #IoT Hub 发布于: 2023-06-13 20:56:14

使用Azure IoT Hub的计划任务可以同时操作多个设备,使用计划任务可以处理如下的场景:

  • 批量更新预期属性
  • 批量更新Tags
  • 批量调用直接方法。

本章向大家展示如何使用.Net Service SDK来创建计划任务,并使用该任务调用直接方法,本章需要使用到之前创建的一个实例,DirectMethodCallSample, 您可以参考文档重新创建该实例:

使用.Net Service SDK调用设备的Direct Method方法

创建一个新的项目

首先使用如下的命令取得设备simDevice的连接字符串,当然这之前你需要先创建好Azure IoT Hub资源以及该设备:

az iot hub device-identity connection-string show --device-id simDevice --hub-name MyIoThubByCli

得到连接字符串之后,先保存起来,后面的代码中需要使用到这个连接字符串。

使用下述的命令创建我们的项目:

dotnet new console -o  ScheduleJob
cd ScheduleJob
dotnet add package Microsoft.Azure.Devices.Client
code .

打开VS code或者其他编辑器之后,在根目录下添加一个文件GlobalUsing.cs, 打开该文件,添加如下的引用:

global using Microsoft.Azure.Devices;
global using Microsoft.Azure.Devices.Shared;
global using System.Text.Json;
global using System.Text;
global using System.Text.Json.Serialization;
global using System.Diagnostics;
global using ScheduleJob;

在根目录下创建一个JobSample.cs的文件,以下述内容替换:

namespace ScheduleJob;

public class JobSample
{
    private readonly JobClient jobClient;
    private readonly string deviceId;

    public JobSample(JobClient client, string device)
    {
        jobClient = client ?? throw new ArgumentNullException(nameof(client));
        deviceId = device ?? throw new ArgumentNullException(nameof(device));

    }

    public async Task RunSampleAsync()
    {
        Console.WriteLine("按回车键开始运行计划任务......");
        Console.ReadLine();


        string methodJobId = Guid.NewGuid().ToString();

        await StartMethodJobAsync(methodJobId);
        await MonitorJobAsync(methodJobId);
        Console.WriteLine("按回车键继续下一个任务.");
        Console.ReadLine();

        string twinUpdateJobId = Guid.NewGuid().ToString();

        await StartTwinUpdateJobAsync(twinUpdateJobId);
        await MonitorJobAsync(twinUpdateJobId);
        Console.WriteLine("按回车键退出。");
        Console.ReadLine();

    }


    public async Task MonitorJobAsync(string jobId)
    {
        JobResponse result;
        do
        {
            result = await jobClient.GetJobAsync(jobId);
            Console.WriteLine("计划任务的状态 : " + result.Status.ToString());
            Thread.Sleep(2000);
        } while ((result.Status != JobStatus.Completed) &&
          (result.Status != JobStatus.Failed));
    }

    public async Task StartMethodJobAsync(string jobId)
    {
        CloudToDeviceMethod directMethod =
          new CloudToDeviceMethod("WriteToConsole", 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("开始调用直接方法");
    }



    public async Task StartTwinUpdateJobAsync(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 = await jobClient.ScheduleTwinUpdateAsync(
            jobId,
            $"DeviceId IN ['{deviceId}']",
            twin,
            DateTime.UtcNow,
            (long)TimeSpan.FromMinutes(2).TotalSeconds);

        Console.WriteLine("开始孪生设备属性更新......");
    }


}

特别是需要注意这里对async以及await的用法,以及使用他们用于计划任务观察的异步模式。

然后打开Program.cs,以如下的内容替换:

Console.WriteLine("使用SAS Key连接字符串连接Azure IoT Hub, 并创建计划任务......");

string s_connectionString = "<您的连接字符串>";

var deviceId = "simDevice";

//验证连接字符串是否是正确的
ValidateConnectionString(args);

using var jobClient = JobClient.CreateFromConnectionString(s_connectionString);


var sample = new JobSample(jobClient, deviceId);
await sample.RunSampleAsync();
await jobClient.CloseAsync();

Console.WriteLine("Done.");

void ValidateConnectionString(string[] appArgs)
{
    if ( appArgs.Any() )
    {
        try 
        {
            var cs = IotHubConnectionStringBuilder.Create(appArgs[0]);
            s_connectionString = cs.ToString();

        } catch ( Exception )
        {
            Console.WriteLine($"错误:无法识别连接字符串参数 `{appArgs[0]}");
            Environment.Exit(-1);
        }

    }
    else
    {
        try 
        {
            _ = IotHubConnectionStringBuilder.Create(s_connectionString);
        } catch(Exception )
        {
            Console.WriteLine("这个Demo需要使用连接字符串连接到Azure IoT Hub");
            Environment.Exit(-1);
        }
    }
}

同时运行这两个应用,即可以看到效果。