使用 IoT 中心 (.NET) 将消息从云发送到设备
Azure IoT 中心是一项完全托管的服务,有助于在数百万台设备和单个解决方案后端之间实现安全可靠的双向通信。
本文介绍如何:
通过 IoT 中心,将云到设备的消息从解决方案后端发送到单个设备
在设备上接收云到设备的消息
从解决方案后端,请求送达确认,确认收到从 IoT 中心发送到设备的消息(反馈)
注意
本文所述的功能只能用于 IoT 中心的标准层。 有关 IoT 中心基本层和标准/免费层的详细信息,请参阅选择适合你的解决方案的 IoT 中心层。
在本文结束时,会运行两个 .NET 控制台应用。
SimulatedDevice:从设备将遥测数据发送到 IoT 中心中创建的应用的修改版本,它连接到 IoT 中心并接收云到设备的消息。
SendCloudToDevice:它通过 IoT 中心将云到设备消息发送到设备应用,然后接收其送达确认。
可以在 IoT 中心的 D2C 和 C2D 消息传送中找到有关“云到设备”消息的详细信息。
先决条件
Visual Studio
将遥测数据从设备发送到 IoT 中心快速入门或使用 IoT 中心配置消息路由一文的完整工作版本。 这篇云到设备文章以快速入门为基本。
确保已在防火墙中打开端口 8883。 本文中的设备示例使用 MQTT 协议,该协议通过端口 8883 进行通信。 在某些公司和教育网络环境中,此端口可能被阻止。 有关解决此问题的更多信息和方法,请参阅连接到 IoT 中心(MQTT)。
在设备应用中接收消息
在本部分,修改设备应用,使其从 IoT 中心接收云到设备消息。
在 Visual Studio 的 SimulatedDevice 项目中,将以下方法添加到 SimulatedDevice 类 。
private static async void ReceiveC2dAsync() { Console.WriteLine("\nReceiving cloud to device messages from service"); while (true) { Message receivedMessage = await s_deviceClient.ReceiveAsync(); if (receivedMessage == null) continue; Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Received message: {0}", Encoding.ASCII.GetString(receivedMessage.GetBytes())); Console.ResetColor(); await s_deviceClient.CompleteAsync(receivedMessage); } }
在 Main 方法中的
Console.ReadLine()
行前面添加以下方法:ReceiveC2dAsync();
在设备收到消息时,ReceiveAsync
方法以异步方式返回收到的消息。 它在可指定的超时期限过后返回 null。 在此示例中,使用默认值一分钟。 当应用收到 null 时,它应继续等待新消息。 此要求是使用 if (receivedMessage == null) continue
行的原因。
对 CompleteAsync()
的调用会通知 IoT 中心,指出已成功处理消息,且可以安全地从设备队列中删除该消息。 无论其使用何种协议,设备都应在处理成功完成后调用此方法。
使用 AMQP 和 HTTPS,但不使用 MQTT,该设备也可以:
- 放弃消息,使 IoT 中心将消息保留在设备队列中供将来使用。
- 拒绝消息,这会永久地从设备队列中删除该消息。
如果发生阻止设备完成、放弃或拒绝消息的情况,IoT 中心会在固定的超时期限过后再次对消息排队以进行传递。 因此,设备应用中的消息处理逻辑必须是幂等的,这样,多次接收相同的消息才会生成相同的结果。
若要获取有关云到设备消息生命周期以及 IoT 中心如何处理云到设备消息的详细信息,请参阅从 IoT 中心发送云到设备的消息。
注意
使用 HTTPS 而不使用 MQTT 或 AMQP 作为传输时,ReceiveAsync
方法将立即返回。 使用 HTTPS 的云到设备消息,其支持模式是间歇连接到设备,且不常检查消息(至少每 25 分钟检查一次)。 发出更多 HTTPS 接收会导致 IoT 中心限制请求。 有关 MQTT、AMQP 和 HTTPS 支持之间的差异的详细信息,请参阅云到设备通信指南和选择通信协议。
获取 IoT 中心连接字符串
本文中,你将创建一个后端服务,用于通过 IoT 中心发送云到设备消息。 若要发送云到设备消息,服务需要服务连接权限。 默认情况下,每个 IoT 中心都使用名为“服务”的共享访问策略创建,该策略会授予此权限。
若要获取 service策略的 IoT 中心连接字符串,请执行以下步骤:
在 Azure 门户中,选择“资源组”。 选择中心所在的资源组,然后从资源列表中选择中心。
在 IoT 中心的左侧窗格上,选择“共享访问策略”。
在策略列表中,选择“service”策略。
复制“主连接字符串”并保存该值。
有关 IoT 中心共享访问策略和权限的详细信息,请参阅访问控制和权限。
发送云到设备的消息
在本部分中,会创建 .NET 控制台应用,用于向模拟设备应用发送云到设备的消息。 需要设备的设备 ID 和 IoT 中心连接字符串。
在 Visual Studio 中,选择“文件”>“新建”>“项目”。 在“创建新项目”中,选择“控制台应用(.NET Framework)”,然后选择“下一步” 。
将项目命名为 SendCloudToDevice,然后选择“下一步”。
接受最新版本的.NET Framework。 选择“创建”来创建项目。
在“解决方案资源管理器”中,右键单击新项目,然后选择“管理 NuGet 包”。
在“管理 NuGet 程序包”中,选择“浏览”,然后搜索并选择“Microsoft.Azure.Devices”。 选择“安装” 。
此步骤会下载、安装 Azure IoT 服务 SDK NuGet 包并添加对它的引用。
在 Program.cs 文件顶部添加以下
using
语句。using Microsoft.Azure.Devices;
将以下字段添加到 Program 类。 将
{iot hub connection string}
占位符值替换为先前在获取 IoT 中心连接字符串中记下的 IoT 中心连接字符串。 将{device id}
占位符值替换为你在将遥测数据从设备发送到 IoT 中心快速入门中添加的设备的设备 ID。static ServiceClient serviceClient; static string connectionString = "{iot hub connection string}"; static string targetDevice = "{device id}";
将以下方法添加到 Program 类,以便将消息发送到设备。
private async static Task SendCloudToDeviceMessageAsync() { var commandMessage = new Message(Encoding.ASCII.GetBytes("Cloud to device message.")); await serviceClient.SendAsync(targetDevice, commandMessage); }
最后,将下面的行添加到 Main 方法。
Console.WriteLine("Send Cloud-to-Device message\n"); serviceClient = ServiceClient.CreateFromConnectionString(connectionString); Console.WriteLine("Press any key to send a C2D message."); Console.ReadLine(); SendCloudToDeviceMessageAsync().Wait(); Console.ReadLine();
在解决方案资源管理器中,右键单击解决方案并选择“设置启动项目”。
在“常见属性”>“启动项目”中,选择“多个启动项目”,然后为 SimulatedDevice 和 SendCloudToDevice 选择“启动”操作 。 选择“确定”保存更改。
按 F5。 这两个应用程序应该都会启动。 选择“SendCloudToDevice”窗口并按“Enter” 。 应会看到设备应用正在接收的消息。
接收送达反馈
可以从 IoT 中心请求每个云到设备消息的送达(或过期)确认。 借助此选项,解决方案后端能够轻松地通知、重试或补偿逻辑。 有关云到设备反馈的详细信息,请参阅 IoT 中心的 D2C 和 C2D 消息传送。
在本部分中,修改 SendCloudToDevice 应用以请求反馈,并接收来自 IoT 中心的反馈。
在 Visual Studio 中的 SendCloudToDevice 项目内,将以下方法添加到 Program 类。
private async static void ReceiveFeedbackAsync() { var feedbackReceiver = serviceClient.GetFeedbackReceiver(); Console.WriteLine("\nReceiving c2d feedback from service"); while (true) { var feedbackBatch = await feedbackReceiver.ReceiveAsync(); if (feedbackBatch == null) continue; Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Received feedback: {0}", string.Join(", ", feedbackBatch.Records.Select(f => f.StatusCode))); Console.ResetColor(); await feedbackReceiver.CompleteAsync(feedbackBatch); } }
请注意,此接收模式与用于从设备应用接收云到设备消息的模式相同。
在 Main 方法中的
serviceClient = ServiceClient.CreateFromConnectionString(connectionString)
后面添加以下行。ReceiveFeedbackAsync();
若要请求针对传递云到设备消息的反馈,必须在 SendCloudToDeviceMessageAsync 方法中指定一个属性。 紧接在
var commandMessage = new Message(...);
行的后面添加以下行。commandMessage.Ack = DeliveryAcknowledgement.Full;
按 F5 运行应用。 应会看到两个应用程序都会启动。 选择“SendCloudToDevice”窗口并按“Enter” 。 应会看到设备应用正在接收的消息,几秒钟后,SendCloudToDevice 应用程序将收到反馈消息。
注意
为简单起见,本文不实现任何重试策略。 在生产代码中,应按暂时性故障处理中所述实现重试策略(例如指数退避)。
后续步骤
本文已介绍了如何发送和接收云到设备的消息。
若要详细了解云到设备的消息,请参阅从 IoT 中心发送云到设备的消息。
若要详细了解 IoT 中心消息格式,请参阅创建和读取 IoT 中心消息。 )。