使用.Net Service SDK调用设备的Direct Method方法
分类: Azure物联网 ◆ 标签: #Azure #IoT Hub # ◆ 发布于: 2023-06-13 20:44:52

在我们这个例子中使用.Net Device SDK
实现一个模拟设备,并在该设备中准备好需要相应的Direct method
方法,之后我们在使用工具来调用该方法,之后使用.Net Serivce SDK
来实现该方法的调用。
使用.Net Device SDK
创建一个模拟设备
通过Azure Cli IoT
扩展工具找到SAS key
以及连接字符串。
az iot hub device-identity connection-string show --device-id simDevice --hub-name MyIoThubByCli
该语句返回的结果就是我们需要的连接字符串,那到该以SAS Key
为基础的连接字符串之后,我们可以使用如下的代码来连接Azure IoT Hub
以及向Azure IoT Hub
发送遥测数据。
注意
代码是基于.Net 6
的
使用.Net
SDK连接到Azure IoT Hub
使用如下的命令创建一个项目,并引入需要的SDK
包:
dotnet new console -o SimDeviceWithCommand
cd SimDeviceWithCommand
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;
然后打开文件Program.cs
, 以如下的内容进行替换:
Console.WriteLine("使用SAS Key连接字符串连接Azure IoT Hub, 并相应直接方法的实例"); string s_connectionString = "<你的IoT Hub连接字符串>"; //验证连接字符串是否是正确的 ValidateConnectionString(args); DeviceClient s_deviceClient = DeviceClient.CreateFromConnectionString(s_connectionString); Console.WriteLine("请同时按 Control - C 退出应用"); using var cts = new CancellationTokenSource(); Console.CancelKeyPress += (sender, eventArgs) => { eventArgs.Cancel = true; cts.Cancel(); Console.WriteLine("退出程序......"); }; //设定1秒的时间间隔 var s_telemetryInterval = TimeSpan.FromSeconds(1); //设定直接方法调用的相应方法 await s_deviceClient.SetMethodHandlerAsync("SetTelemetryInterval", SetTelemetryInterval, null ); await SendDeviceToCloudMessageAsync(cts.Token); await s_deviceClient.CloseAsync(); s_deviceClient.Dispose(); Console.WriteLine("模拟设备退出!"); async Task SendDeviceToCloudMessageAsync(CancellationToken ct) { //初始化遥测的配置 double minTemperature = 20; double minHumidity = 60; var rand = new Random(); while ( !ct.IsCancellationRequested ) { double currentTemperature = minTemperature + rand.NextDouble() * 15; double currentHumidity = minHumidity + rand.NextDouble() * 20; //创建Json编码的消息 string messageBody = JsonSerializer.Serialize( new { temperature = currentTemperature, humidity = currentHumidity, } ); using var message = new Message(Encoding.ASCII.GetBytes(messageBody)) { ContentType = "application/json", ContentEncoding = "utf-8", }; message.Properties.Add("temperatureAlert", (currentTemperature> 30 )? "true":"false"); await s_deviceClient.SendEventAsync(message); Console.WriteLine($"{DateTime.Now} > 发送消息:{messageBody}"); await Task.Delay(s_telemetryInterval, ct); } } 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); } } } //直接方法call back函数 Task<MethodResponse> SetTelemetryInterval(MethodRequest methodRequest, object userContext) { var data = Encoding.UTF8.GetString(methodRequest.Data); // 检查应用数据 if (int.TryParse(data, out int telemetryIntervalInSeconds)) { s_telemetryInterval = TimeSpan.FromSeconds(telemetryIntervalInSeconds); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine($"遥测数据发送时间间隔更改为 {s_telemetryInterval}"); Console.ResetColor(); // Acknowlege the direct method call with a 200 success message string result = $"{调用结果:调用直接方法结果: {methodRequest.Name}}"; return Task.FromResult(new MethodResponse(Encoding.UTF8.GetBytes(result), 200)); } else { // Acknowlege the direct method call with a 400 error message string result = "{调用结果 : 参数非法}"; return Task.FromResult(new MethodResponse(Encoding.UTF8.GetBytes(result), 400)); } }
注意这段代码里几段需要注意的地方:
//设定直接方法调用的相应方法 await s_deviceClient.SetMethodHandlerAsync("SetTelemetryInterval", SetTelemetryInterval, null );
该方法是在Device SDK上调用,设定直接方法的call back函数。
另外需要注意的是方法SetTelemetryInterval
的定义形式。
在控制台中运行该应用: dotnet run
等候应用运行起来后,我们登录到Azure Portal
找到Azure IoT Hub
资源,并在其中找到设备列表,找到这个设备,点击该设备之后,在如下界面直接调用直接方法:
然后如下图调用:
直接调用之后,可以有如下效果:
使用.Net Service SDK
调用直接方法
我们使用.Net Service SDK
调用直接方法,我们需要新建一个应用,使用如下的步骤来新建一个应用。
在次之前我们先使用Azure Cli IoT
扩展工具取得Service SDK
需要的连接字符串:
az iot hub connection-string show --hub-name MyIoTHubByCli --policy-name service
dotnet new console -o CallDirectMethodByServiceSDK
cd CallDirectMethodByServiceSDK
dotnet add package Microsoft.Azure.Devices
code .
打开VS code
或者其他编辑器之后,在根目录下添加一个文件GlobalUsing.cs
, 打开该文件,添加如下的引用:
global using Microsoft.Azure.Devices; global using System.Text.Json; global using System.Text;
然后打开文件Program.cs
, 以如下的内容进行替换:
string s_connectionString = "您的Service SDK连接字符串"; Console.WriteLine("使用.Net Service SDK直接调用设备直接方法实例"); //验证连接字符串 ValidateConnectionString(args); ServiceClient s_serviceClient = ServiceClient.CreateFromConnectionString(s_connectionString); await InvokeMethodAsync(); s_serviceClient.Dispose(); Console.WriteLine("按任意键退出应用"); Console.ReadKey(); // 调用直接方法 async Task InvokeMethodAsync() { var methodInvocation = new CloudToDeviceMethod("SetTelemetryInterval") { ResponseTimeout = TimeSpan.FromSeconds(30), }; methodInvocation.SetPayloadJson("10"); //延迟10秒 // 调用直接方法,并等待结果 var response = await s_serviceClient.InvokeDeviceMethodAsync("simDevice", methodInvocation); Console.WriteLine($"\n调用结果: {response.Status}, 数据:\n\t{response.GetPayloadAsJson()}"); } 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); } } }
开两个控制台窗口,同时运行该应用就可以看到效果了。