另外一个调用直接方法处理实例(Direct Method)
分类: Azure物联网 ◆ 标签: #Azure #IoT Hub # ◆ 发布于: 2023-06-13 20:47:06

本节我们再来学习一个新的用于处理直接方法调用的实例,希望大家能够直接从代码中学习到更多,另外需要注意的是,我们所有的代码都是基于.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 DirectMethodCallSample
cd DirectMethodCallSample
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 DirectMethodCallSample;
创建一个新类DirectMethodCallSample
, 填充如下的内容:
namespace DirectMethodCallSample; public class MethodSample { private readonly DeviceClient _deviceClient; private class DeviceData { [JsonPropertyName("name")] public string? Name { get; set; } } public MethodSample(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("应用被取消,即将退出。"); }; //设置连接变化call back函数 _deviceClient.SetConnectionStatusChangesHandler(ConnectionStatusChangeHandler); //根据我们对MQTT协议,以及AMQP协议的理解,直接方法调用或者是twin更改,都是监听消息,因此 //当第一个方法处理加入时,实际上就是在监听来自iot hub的消息。 // 添加一个回调函数用于直接方法'WriteToConsole'的监听。 await _deviceClient.SetMethodHandlerAsync("WriteToConsole", WriteToConsoleAsync, null, cts.Token); // 添加回调函数用于直接方法'GetDeviceName'调用。 await _deviceClient.SetMethodHandlerAsync( "GetDeviceName", GetDeviceNameAsync, new DeviceData { Name = "DeviceClientMethodSample" }, cts.Token); var timer = Stopwatch.StartNew(); Console.WriteLine($"请使用Azure Portal或者Azure IoT Explorer调用直接方法:GetDeviceName或者WriteToConsole。"); Console.WriteLine($"等待直接方法调用,等待时长为:{sampleRunningTime} ..."); while (!cts.IsCancellationRequested && (sampleRunningTime == Timeout.InfiniteTimeSpan || timer.Elapsed < sampleRunningTime)) { await Task.Delay(1000); } // 可以使用如下方法取消对直接方法调用的订阅。 await _deviceClient.SetMethodHandlerAsync( "GetDeviceName", null, null); await _deviceClient.SetMethodHandlerAsync( "WriteToConsole", null, null); } private void ConnectionStatusChangeHandler(ConnectionStatus status, ConnectionStatusChangeReason reason) { Console.WriteLine($"\n连接状态变为:{status}."); Console.WriteLine($"连接状态改变的原因是: {reason}.\n"); } private Task<MethodResponse> WriteToConsoleAsync(MethodRequest methodRequest, object userContext) { Console.WriteLine($"\t *** {methodRequest.Name} was called."); Console.WriteLine($"\t{methodRequest.DataAsJson}\n"); return Task.FromResult(new MethodResponse(new byte[0], 200)); } private Task<MethodResponse> GetDeviceNameAsync(MethodRequest methodRequest, object userContext) { Console.WriteLine($"\t *** {methodRequest.Name} was called."); MethodResponse retValue; if (userContext == null) { retValue = new MethodResponse(new byte[0], 500); } else { var deviceData = (DeviceData)userContext; string result = JsonSerializer.Serialize(deviceData); retValue = new MethodResponse(Encoding.UTF8.GetBytes(result), 200); } return Task.FromResult(retValue); } }
注意该类中关于直接方法调用的影响函数是如何设计的,需要理解针对于MQTT
以及AMQP
协议,直接方法调用实际上就是订阅不同的TOPIC
,也可以直接取消订阅。
添加了该类之后,打开Program.cs
,使用如下的内容替换:
Console.WriteLine("使用SAS Key连接字符串连接Azure IoT Hub, 并调用直接方法的实例"); 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 MethodSample(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); } } }
通过工具进行直接方法调用该,可以看到调用的结果,另外注意如果这个时候网络出现问题,会发现,SDK会自动进行重连。
如下图: