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特性的支持可能存在问题,应避免使用。

相关推荐
HugoStudio_SWAN35 分钟前
【按键反馈】C++ 实现键盘烟花秀
开发语言·c++·学习·程序人生
AI 编程助手GPT1 小时前
Bun 1.4 正式发布:从 Zig 改写为 Rust,内置浏览器、图片处理和并行测试
开发语言·人工智能·后端·ai·chatgpt
paopaokaka_luck1 小时前
基于springboot3+vue3的飞行器模型实验室预约管理系统(协同过滤算法、Echarts图形化分析)
开发语言·推荐算法
lingchen19061 小时前
用MATLAB r2010b和r2016b求解微分方程组
开发语言·算法·matlab
ttwosix1 小时前
JavaEE初阶 多线程 3
java·开发语言
CSDN_RTKLIB1 小时前
模型空间、布局控件、自定义块
c#
峥嵘life1 小时前
Android16 系统 APEX 模块调试总结
android·大数据·开发语言
OPEN-F1 小时前
C++进阶教程:类与对象深入
java·开发语言·c++
z落落1 小时前
C# WinForm TCP 服务器+WinForm TCP 客户端
服务器·tcp/ip·c#