Skip to main content

使用.Net SDK处理孪生设备预期属性更新和上报属性更新

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

本节我们学习设备代码如何影响孪生设备的预期属性更新以及上报属性的更新,希望大家能够直接从代码中学习到更多,另外需要注意的是,我们所有的代码都是基于.Net 6,所以如果你想从我们的这些代码中收益,您需要安装.Net 6的SDK。

创建一个新的项目

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

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

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

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

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

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

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

在根目录下创建一个新的文件:TwinSample.cs, 然后使用如下的内容:

namespace DeviceTwinSample;

public class TwinSample
{
    private readonly DeviceClient _deviceClient;

    public TwinSample(DeviceClient deviceClient)
    {
        _deviceClient = deviceClient ?? throw new ArgumentNullException(nameof(deviceClient));
    }

    public async Task RunSampleAsync(TimeSpan sampleRunningTime)
    {
        Console.WriteLine("按control - C 退出应用。");
        using var cts = new CancellationTokenSource(sampleRunningTime);
        Console.CancelKeyPress += (sender, eventArgs) =>
        {
            eventArgs.Cancel = true;
            cts.Cancel();
            Console.WriteLine("应用运行被取消,正在退出。");
        };

        //定义预期属性改变的回调函数
        await _deviceClient.SetDesiredPropertyUpdateCallbackAsync(OnDesiredPropertyChangedAsync, null);

        Console.WriteLine("从IoT Hub取回Twin文档......");
        Twin twin = await _deviceClient.GetTwinAsync();

        Console.WriteLine("\t接收到的初始的Twin值:");
        Console.WriteLine($"\t{twin.ToJson()}");

        Console.WriteLine("向IOT Hub上报属性:");
        TwinCollection reportedProperties = new TwinCollection();
        reportedProperties["DateTimeLastAppLaunch"] = DateTime.UtcNow;

        await _deviceClient.UpdateReportedPropertiesAsync(reportedProperties);

        var timer = Stopwatch.StartNew();
        Console.WriteLine($"使用Azure IoT Hub或者Azure IoT explorer更改Device Twin 预期属性。");

        Console.WriteLine($"等待接受预期属性的更改, 等待时间是:{sampleRunningTime} ...");
        while (!cts.IsCancellationRequested
            && (sampleRunningTime == Timeout.InfiniteTimeSpan || timer.Elapsed < sampleRunningTime))
        {
            await Task.Delay(1000);
        }

        // 取消预订预期属性更改事件
        await _deviceClient.SetDesiredPropertyUpdateCallbackAsync(null, null);
    }

    private async Task OnDesiredPropertyChangedAsync(TwinCollection desiredProperties, object userContext)
    {
        var reportedProperties = new TwinCollection();

        Console.WriteLine("\t预期属性更改要求:");
        Console.WriteLine($"\t{desiredProperties.ToJson()}");

        foreach (KeyValuePair<string, object> desiredProperty in desiredProperties)
        {
            Console.WriteLine($"Setting {desiredProperty.Key} to {desiredProperty.Value}.");
            reportedProperties[desiredProperty.Key] = desiredProperty.Value;
        }

        Console.WriteLine("\tAlso setting current time as reported property");
        reportedProperties["DateTimeLastDesiredPropertyChangeReceived"] = DateTime.UtcNow;

        await _deviceClient.UpdateReportedPropertiesAsync(reportedProperties);
    }
}

该文件里需要注意的是如何监听预期属性更改的事件,以及如何更新上报属性。

打开文件Promgram.cs, 使用如下的内容替换:

Console.WriteLine("使用SAS Key连接字符串连接Azure IoT Hub, 并使用Device Twin的实例:");

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

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

DeviceClient s_deviceClient = DeviceClient.CreateFromConnectionString(s_connectionString);

using var deviceClient = DeviceClient.CreateFromConnectionString(
                s_connectionString,
                TransportType.Mqtt);

var runningTime = Timeout.InfiniteTimeSpan;

var sample = new TwinSample(deviceClient);
await sample.RunSampleAsync(runningTime);
await deviceClient.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);
        }
    }
}

运行该实例,然后查看效果。