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:Connectiot:Publishiot: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 直接加载。

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

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

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

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

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

相关推荐
泡海椒9 分钟前
规则引擎对比:JQuick-Java vs Drools 轻量场景选型对比
java·开发语言
泡泡鱼(敲代码中)31 分钟前
Python 容器类型学习笔记:列表、元组、字典、集合
开发语言·笔记·python·pycharm
2501_9336707940 分钟前
平台招商运营校招能力模型:数据分析、SQL与增长场景拆解
开发语言
菜鸟~noob2331 小时前
【Bonjour】华为Peerium架构深度解析:从冯·诺依曼到百万处理器“一台计算机”,附MATLAB性能仿真【含matlab代码,可直接运行】
开发语言·matlab·华为·peerium
白远山2 小时前
24小时自助健身房系统开发实战:从需求分析到完整指南
java·开发语言·数据库·数据挖掘·需求分析
shmily麻瓜小菜鸡4 小时前
TDD(测试驱动开发)详解
开发语言·javascript·typescript·node.js·ecmascript
三克的油4 小时前
java-学习1
java·开发语言·学习
星期八不上发条4 小时前
智能指针是什么?使用场景,循环引用解决办法,面试回答
开发语言·c++·stl
tang_04274 小时前
【Hi.Ltd 专题】第7期:Threading 采集线程、锁与 LRU 缓存
经验分享·c#·hi.ltd系列
OKkankan4 小时前
Python 基础进阶(三):从函数、类到 asyncio 与 FastAPI 后端开发实战
开发语言·python