C#环境中部署MQTT客户端

Windows C#环境,推荐的方案是使用 MQTTnet 这个高性能、成熟的.NET库。结合AWS官方的 .NET SDK或社区方案,可以很好地完成你的需求。

下面是具体的实施步骤和代码示例。

核心实施步骤

第一步:云端准备 (AWS IoT Core)

这一步与上一轮回答基本一致,你需要完成以下操作:

  1. 创建"事物" (Thing):在AWS IoT Core控制台中,为你的印花设备创建一个"事物"。

  2. 生成并下载凭证 :为这个"事物"生成并下载安全凭证,包括设备证书 (.pem.crt)、私钥 (.private.pem.key)和根CA证书 (如 AmazonRootCA1.pem)。

  3. 创建并附加策略 (Policy) :创建一个IoT策略,允许设备执行 iot:Connect、iot:Publish 和 iot:Subscribe 操作,并将该策略附加到设备证书上。

  4. 获取终端节点 (Endpoint) :在AWS IoT Core控制台的"设置"页面,找到你的终端节点地址 (例如 xxxxxxxxxx-ats.iot.<region>.amazonaws.com)。

第二步:创建C#项目并安装NuGet包

在你的Windows 10/11开发环境(如Visual Studio)中,创建或打开你的C#项目,然后通过NuGet包管理器安装以下核心库:

  • MQTTnet:核心MQTT客户端库。

  • MQTTnet.Extensions.ManagedClient (可选):提供自动重连和消息队列管理等高级功能。

  • System.Security.Cryptography.Pkcs:用于处理证书。

在"程序包管理器控制台"中运行以下命令:

bash 复制代码
Install-Package MQTTnet
Install-Package MQTTnet.Extensions.ManagedClient

注意 :你可能需要额外引入 Oocx.ReadX509CertificateFromPem 等辅助库来简化从PEM格式文件加载证书的过程。

第三步:编写C#连接代码

以下是一个使用 MQTTnet 连接AWS IoT Core并发布设备状态的完整示例。核心步骤包括:加载证书、配置TLS、发起连接和发布消息。

cs 复制代码
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Extensions.ManagedClient;

namespace MqttPrinterStatus
{
    class Program
    {
        // 1. 定义AWS IoT Core的终端节点和端口
        private const string AwsIotEndpoint = "xxxxxxxxxx-ats.iot.<region>.amazonaws.com";
        private const int AwsIotPort = 8883; // MQTT over TLS端口

        // 2. 定义证书路径(请替换为你的实际路径)
        private const string CaCertPath = @"C:\certs\AmazonRootCA1.pem";
        private const string DeviceCertPath = @"C:\certs\device-certificate.pem.crt";
        private const string DevicePrivateKeyPath = @"C:\certs\device-private.pem.key";

        static async Task Main(string[] args)
        {
            // 3. 加载证书
            var caCert = new X509Certificate2(CaCertPath);
            var deviceCert = LoadCertificateWithPrivateKey(DeviceCertPath, DevicePrivateKeyPath);

            // 4. 创建MQTT客户端选项
            var options = new ManagedMqttClientOptionsBuilder()
                .WithClientOptions(new MqttClientOptionsBuilder()
                    .WithTcpServer(AwsIotEndpoint, AwsIotPort)
                    .WithTls(new MqttClientOptionsBuilderTlsParameters
                    {
                        UseTls = true,
                        Certificates = new List<X509Certificate> { caCert, deviceCert },
                        AllowUntrustedCertificates = false,
                        IgnoreCertificateChainErrors = false,
                        IgnoreCertificateRevocationErrors = false
                    })
                    .WithClientId("YourPrinterDeviceId") // 建议使用Thing名称
                    .WithCleanSession()
                    .Build())
                .Build();

            // 5. 创建并启动托管客户端(支持自动重连)
            var mqttClient = new MqttFactory().CreateManagedMqttClient();
            await mqttClient.StartAsync(options);

            // 6. 订阅云端指令(可选)
            await mqttClient.SubscribeAsync("printer/command");

            // 7. 模拟发送设备状态
            while (true)
            {
                // 构造一个JSON格式的状态消息
                var statusMessage = $"{{\"deviceId\":\"Printer01\",\"status\":\"Online\",\"printerStatus\":\"Ready\",\"timestamp\":\"{DateTime.UtcNow:o}\"}}";
                var message = new MqttApplicationMessageBuilder()
                    .WithTopic("device/status")
                    .WithPayload(Encoding.UTF8.GetBytes(statusMessage))
                    .WithQualityOfServiceLevel(MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce)
                    .Build();

                await mqttClient.PublishAsync(message);
                Console.WriteLine($"已发送状态: {statusMessage}");
                
                await Task.Delay(TimeSpan.FromSeconds(30)); // 每30秒发送一次
            }
        }

        // 辅助方法:从PEM文件加载带有私钥的证书
        private static X509Certificate2 LoadCertificateWithPrivateKey(string certPath, string keyPath)
        {
            // 这里需要结合第三方库如 Oocx.ReadX509CertificateFromPem 或使用 OpenSSL 转换
            // 为简化,此处假设已有转换好的 .pfx 文件,或使用其他方法加载
            // 实际生产环境建议使用更健壮的加载方式
            var certPem = File.ReadAllText(certPath);
            var keyPem = File.ReadAllText(keyPath);
            
            // 可以使用 BouncyCastle 或参考以下方式:
            // 示例:使用 Oocx.ReadX509CertificateFromPem 库
            // var reader = new Oocx.ReadX509CertificateFromPem.CertificateFromPemReader();
            // return reader.LoadCertificateWithPrivateKeyFromStrings(certPem, keyPem);
            
            // 警告:下面的代码仅为演示,实际需要正确实现PEM到X509Certificate2的转换。
            throw new NotImplementedException("请使用正确的PEM加载方式,例如结合BouncyCastle或Oocx库。");
        }
    }
}
第四步:测试与验证
  1. 编译运行:在Visual Studio中编译并运行你的C#程序。

  2. 查看控制台日志:确认程序成功连接并开始发送状态消息。

  3. 云端验证:

    • 在AWS IoT Core控制台的"MQTT测试客户端"中,订阅 device/status 主题,验证是否能收到设备发送的JSON状态数据。

    • 在"MQTT测试客户端"中,向 printer/command 主题发布消息,测试设备是否能接收到云端指令。

关键注意事项与最佳实践

  • 证书转换是关键难点 :在C#中直接使用 .pem 格式的证书和私钥较为复杂。你可以采用以下方式:

    • 使用 OpenSSL 将 .pem 证书和私钥合并为 .pfx 格式,然后使用 X509Certificate2 直接加载。

    • 在项目中集成 BouncyCastle 或 Oocx.ReadX509CertificateFromPem 等库来处理PEM格式。

  • 使用托管客户端 :建议使用 ManagedMqttClient,它能自动处理网络中断后的重连和消息队列,提升应用稳定性。

  • 消息格式 :推荐使用结构化的 JSON 格式来发送设备状态,便于云端和其他服务解析和处理。

  • 错误处理 :务必添加 try-catch 块来捕获连接失败、发布失败等异常,并进行日志记录。

  • 避免使用保留消息和遗嘱消息:根据社区反馈,AWS IoT Core 对这两种MQTT特性的支持可能存在问题,应避免使用。

相关推荐
大都督会赢的11 分钟前
C++第一节课
开发语言·c++
“AI国潮设计-小江”16 分钟前
【AIGC实战】Python+Stable Diffusion打造“英歌舞财神”IP,解锁“马到成功”等爆款情绪营销文案设计
开发语言·人工智能·python·prompt·aigc
小王C语言33 分钟前
Qt常用控件:容器类控件,标题分组框、标签页(浏览器标签)
开发语言·qt
我是唐青枫1 小时前
Kotlin Delegation 委托详解
开发语言·kotlin
qq_406981031 小时前
共享变量一 关于extern与const
开发语言·c++
FRing032 小时前
JavaScript入门到精通三十二(深拷贝、浅拷贝、递归函数)
开发语言·前端·javascript
小嘉丶学长3 小时前
Day14 · 字典与集合
java·开发语言·网络·python·学习·1024程序员节
迪菲赫尔曼3 小时前
【基础篇 11】把官方源码放到服务器:版本、解压层级和安装位置,一次弄清楚
运维·服务器·开发语言·人工智能·python·yolo·目标检测
chari克里4 小时前
QT5.15.2 + msvc2022部署全流程说明(windows可联网环境)
开发语言·c++·qt
Hello.Reader4 小时前
tsrs 技术解析用 Rust 移植 TypeScript 7,类型检查还能怎样提速?
开发语言·rust·typescript