C# MQTT客户端

使用的第三方库:MQTTnet

MQTT数据接收事件参数

namespace Demo
{
    /// <summary>
    /// MQTT数据接收事件参数
    /// </summary>
    public class MqttReceivedEventArgs : EventArgs
    {
        /// <summary>
        /// 主题
        /// </summary>
        public string Topic { get; }
        /// <summary>
        /// 消息
        /// </summary>
        public string Message { get; }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="topic"></param>
        /// <param name="message"></param>
        public MqttReceivedEventArgs(string topic, string message)
        {
            Topic = topic ?? throw new ArgumentNullException(nameof(topic));
            Message = message ?? throw new ArgumentNullException(nameof(message));
        }
    }
}
View Code

MQTT本地客户端

using Microsoft.Extensions.Logging;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Protocol;
using System.Text;

namespace Demo
{
    /// <summary>
    /// MQTT 本地客户端
    /// </summary>
    public class MqttToLocalClient
    {
        /// <summary>
        /// 客户端ID
        /// </summary>
        private readonly string _clientId = "RcsMqttClient_" + Guid.NewGuid();
        /// <summary>
        /// 服务器地址
        /// </summary>
        private string _host = "127.0.0.1";
        /// <summary>
        /// 服务器端口
        /// </summary>
        private int _port = 1883;
        /// <summary>
        /// 是否需要重连
        /// </summary>
        private bool _needToReconnect = true;
        /// <summary>
        /// 需要订阅的主题
        /// </summary>
        private List<string> _topics = new();
        /// <summary>
        /// 日志服务
        /// </summary>
        private readonly ILogger? _logger;
        /// <summary>
        /// MQTT客户端
        /// </summary>
        private IMqttClient? _mqttClient;
        /// <summary>
        /// MQTT客户端选项
        /// </summary>
        private MqttClientOptions? _mqttClientOptions;
        /// <summary>
        /// 消息接收事件
        /// </summary>
        public event Func<MqttReceivedEventArgs, Task>? MessageReceivedEvent;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger"></param>
        public MqttToLocalClient(ILogger<MqttToLocalClient>? logger = null)
        {
            _logger = logger;
        }
        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="host"></param>
        /// <param name="port"></param>
        /// <param name="needToReconnect"></param>
        /// <returns></returns>
        public async Task InitAsync(string host = "127.0.0.1", int port = 1883, bool needToReconnect = true)
        {
            // 客户端参数
            _host = host;
            _port = port;
            _needToReconnect = needToReconnect;
            // 创建连接
            await ConnectAsync();
            // 判断连接状态的线程
            CheckConnectThread();
        }
        /// <summary>
        /// 创建连接
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        private async Task ConnectAsync()
        {
            // 客户端参数
            _mqttClientOptions = new MqttClientOptionsBuilder()
                .WithTcpServer(_host, _port)
                .WithClientId(_clientId)
                .Build();
            // 创建客户端
            _mqttClient = new MqttFactory().CreateMqttClient();
            // 连接成功事件
            _mqttClient.ConnectedAsync += MqttClient_ConnectedAsync;
            // 断开连接事件
            _mqttClient.DisconnectedAsync += MqttClient_DisconnectedAsync;
            // 消息接收事件
            _mqttClient.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceivedAsync;
            // 开始连接
            var result = await _mqttClient.ConnectAsync(_mqttClientOptions);
            if (result.ResultCode != MqttClientConnectResultCode.Success)
            {
                throw new Exception($"Mqtt connect fail, Result code {result.ResultCode}");
            }
        }
        /// <summary>
        /// 订阅主题
        /// </summary>
        /// <param name="topic"></param>
        /// <returns></returns>
        private async Task SubscribeAsync(string topic)
        {
            if (_mqttClient?.IsConnected == true)
            {
                var mqttSubscribeOptions = new MqttFactory().CreateSubscribeOptionsBuilder()
                .WithTopicFilter(
                    f =>
                    {
                        f.WithTopic(topic).WithQualityOfServiceLevel(MqttQualityOfServiceLevel.ExactlyOnce);
                    })
                .Build();
                var response = await _mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);
            }
        }
        /// <summary>
        /// 订阅主题
        /// </summary>
        /// <param name="topics"></param>
        /// <returns></returns>
        public async Task SubscribeAsync(List<string> topics)
        {
            if (_mqttClient?.IsConnected == true)
            {
                // 缓存
                if (_topics != topics)
                {
                    _topics = topics;
                }
                // 遍历
                foreach (string topic in _topics)
                {
                    await SubscribeAsync(topic);
                }
            }
        }
        /// <summary>
        /// 发布消息
        /// </summary>
        /// <param name="topic"></param>
        /// <param name="message"></param>
        /// <param name="qos"></param>
        /// <returns></returns>
        public async Task PublishAsync(string topic, string message, int qos)
        {
            if (_mqttClient?.IsConnected == true)
            {
                _logger?.LogDebug("Mqtt message publish: {0}, {1}", topic, message);
                var applicationMessage = new MqttApplicationMessageBuilder()
                .WithTopic(topic)
                .WithPayload(message)
                .WithQualityOfServiceLevel((MqttQualityOfServiceLevel)qos)
                .Build();
                await _mqttClient.PublishAsync(applicationMessage, CancellationToken.None);
            }
        }
        /// <summary>
        /// 连接成功事件
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        private async Task MqttClient_ConnectedAsync(MqttClientConnectedEventArgs arg)
        {
            _logger?.LogInformation("Mqtt connected, IP: {0}, IsSessionPresent: {1}", _host, arg.ConnectResult.IsSessionPresent);
            await Task.CompletedTask;
        }
        /// <summary>
        /// 断开连接事件
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        private async Task MqttClient_DisconnectedAsync(MqttClientDisconnectedEventArgs arg)
        {
            _logger?.LogInformation("Mqtt disconnected, IP: {0}, Reason: {1}, IsSessionPresent: {2}", _host, arg.Reason.ToString(), arg.ClientWasConnected);
            await Task.CompletedTask;
        }
        /// <summary>
        /// 消息接收事件
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        private async Task MqttClient_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs arg)
        {
            try
            {
                // 话题
                string topic = arg.ApplicationMessage.Topic;
                // 接收的数据
                byte[] data = arg.ApplicationMessage.PayloadSegment.ToArray();
                // 接收的字符串
                string message = Encoding.UTF8.GetString(data);
                _logger?.LogDebug("Mqtt message received: {0}, {1}", topic, message);
                // 数据接收事件
                MessageReceivedEvent?.Invoke(new MqttReceivedEventArgs(topic, message));
                await Task.CompletedTask;
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "MQTT接收数据的线程报错");
            }
        }
        /// <summary>
        /// 判断连接状态的线程
        /// </summary>
        private void CheckConnectThread()
        {
            Task.Run(async () =>
            {
                while (true)
                {
                    try
                    {
                        // 判断连接状态
                        if (_needToReconnect && _mqttClient?.IsConnected != true)
                        {
                            // 重新连接
                            await ConnectAsync();
                            // 订阅主题
                            await SubscribeAsync(_topics);
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger?.LogError(ex, "MQTT判断连接状态的线程报错");
                    }
                    await Task.Delay(1000);
                }
            });
        }
    }
}
View Code

MQTT远程客户端

using Microsoft.Extensions.Logging;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Protocol;
using MQTTnet.Server;
using System.Text;

namespace Demo
{
    /// <summary>
    /// MQTT 远程客户端
    /// </summary>
    public class MqttToRemoteClient
    {
        /// <summary>
        /// 客户端ID
        /// </summary>
        private string? _clientId;
        /// <summary>
        /// 服务器地址
        /// </summary>
        private string? _host;
        /// <summary>
        /// 服务器端口
        /// </summary>
        private int _port = 1883;
        /// <summary>
        /// 是否需要重连
        /// </summary>
        private bool _needToReconnect = true;
        /// <summary>
        /// 需要订阅的主题
        /// </summary>
        private List<string> _topics = new();
        /// <summary>
        /// 初始化标志
        /// </summary>
        private bool _initFlag = false;
        /// <summary>
        /// 日志服务
        /// </summary>
        private readonly ILogger? _logger;
        /// <summary>
        /// MQTT客户端
        /// </summary>
        private IMqttClient? _mqttClient;
        /// <summary>
        /// MQTT客户端选项
        /// </summary>
        private MqttClientOptions? _mqttClientOptions;
        /// <summary>
        /// MQTT客户端锁
        /// </summary>
        private readonly object _lock = new();
        /// <summary>
        /// 消息接收事件
        /// </summary>
        public event Func<MqttReceivedEventArgs, Task>? MessageReceivedEvent;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger"></param>
        public MqttToRemoteClient(ILogger<MqttToLocalClient>? logger = null)
        {
            _logger = logger;
        }
        /// <summary>
        /// 初始化
        /// </summary>
        public void Init()
        {
            if (_initFlag == false)
            {
                // 判断连接状态的线程
                CheckConnectThread();
                _initFlag = true;
            }
        }
        /// <summary>
        /// 更新MQTT信息
        /// </summary>
        /// <param name="clientId"></param>
        /// <param name="host"></param>
        /// <param name="port"></param>
        /// <param name="needToReconnect"></param>
        /// <returns></returns>
        public async Task UpdMqttInfoAsync(string clientId, string host, int port = 1883, bool needToReconnect = true)
        {
            await Task.Run(() =>
            {
                lock (_lock)
                {
                    _clientId = clientId;
                    _host = host;
                    _port = port;
                    _needToReconnect = needToReconnect;
                }
            });
        }
        /// <summary>
        /// 创建连接
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        private async Task ConnectAsync()
        {
            // 客户端参数
            _mqttClientOptions = new MqttClientOptionsBuilder()
                .WithTcpServer(_host, _port)
                .WithClientId(_clientId)
                .Build();
            // 创建客户端
            _mqttClient = new MqttFactory().CreateMqttClient();
            // 连接成功事件
            _mqttClient.ConnectedAsync += MqttClient_ConnectedAsync;
            // 断开连接事件
            _mqttClient.DisconnectedAsync += MqttClient_DisconnectedAsync;
            // 消息接收事件
            _mqttClient.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceivedAsync;
            // 开始连接
            var result = await _mqttClient.ConnectAsync(_mqttClientOptions);
            if (result.ResultCode != MqttClientConnectResultCode.Success)
            {
                throw new Exception($"Mqtt connect fail, Result code {result.ResultCode}");
            }
        }
        /// <summary>
        /// 断开连接
        /// </summary>
        /// <param name="needToReconnect"></param>
        /// <returns></returns>
        public async Task DisconnectAsync(bool needToReconnect = false)
        {
            await Task.Run(() =>
            {
                lock (_lock)
                {
                    _needToReconnect = needToReconnect;
                    _mqttClient.DisconnectAsync().Wait();
                }
            });
        }
        /// <summary>
        /// 订阅主题
        /// </summary>
        /// <param name="topic"></param>
        /// <returns></returns>
        private async Task SubscribeAsync(string topic)
        {
            if (_mqttClient?.IsConnected == true)
            {
                var mqttSubscribeOptions = new MqttFactory().CreateSubscribeOptionsBuilder()
                .WithTopicFilter(
                    f =>
                    {
                        f.WithTopic(topic).WithQualityOfServiceLevel(MqttQualityOfServiceLevel.ExactlyOnce);
                    })
                .Build();
                var response = await _mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);
            }
        }
        /// <summary>
        /// 订阅主题
        /// </summary>
        /// <param name="topics"></param>
        /// <returns></returns>
        public async Task SubscribeAsync(List<string> topics)
        {
            if (_mqttClient?.IsConnected == true)
            {
                // 缓存
                if (_topics != topics)
                {
                    _topics = topics;
                }
                // 遍历
                foreach (string topic in _topics)
                {
                    await SubscribeAsync(topic);
                }
            }
        }
        /// <summary>
        /// 发布消息
        /// </summary>
        /// <param name="topic"></param>
        /// <param name="message"></param>
        /// <param name="qos"></param>
        /// <returns></returns>
        public async Task PublishAsync(string topic, string message, int qos)
        {
            if (_mqttClient?.IsConnected == true)
            {
                _logger?.LogDebug("Mqtt message publish: {0}, {1}", topic, message);
                var applicationMessage = new MqttApplicationMessageBuilder()
                .WithTopic(topic)
                .WithPayload(message)
                .WithQualityOfServiceLevel((MqttQualityOfServiceLevel)qos)
                .Build();
                await _mqttClient.PublishAsync(applicationMessage, CancellationToken.None);
            }
        }
        /// <summary>
        /// 连接成功事件
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        private async Task MqttClient_ConnectedAsync(MqttClientConnectedEventArgs arg)
        {
            _logger?.LogInformation("Mqtt connected, IP: {0}, IsSessionPresent: {1}", _host, arg.ConnectResult.IsSessionPresent);
            await Task.CompletedTask;
        }
        /// <summary>
        /// 断开连接事件
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        private async Task MqttClient_DisconnectedAsync(MqttClientDisconnectedEventArgs arg)
        {
            _logger?.LogInformation("Mqtt disconnected, IP: {0}, Reason: {1}, IsSessionPresent: {2}", _host, arg.Reason.ToString(), arg.ClientWasConnected);
            await Task.CompletedTask;
        }
        /// <summary>
        /// 消息接收事件
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        private async Task MqttClient_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs arg)
        {
            try
            {
                // 话题
                string topic = arg.ApplicationMessage.Topic;
                // 接收的数据
                byte[] data = arg.ApplicationMessage.PayloadSegment.ToArray();
                // 接收的字符串
                string message = Encoding.UTF8.GetString(data);
                _logger?.LogDebug("Mqtt message received: {0}, {1}", topic, message);
                // 数据接收事件
                MessageReceivedEvent?.Invoke(new MqttReceivedEventArgs(topic, message));
                await Task.CompletedTask;
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "MQTT接收数据的线程报错");
            }
        }
        /// <summary>
        /// 判断连接状态的线程
        /// </summary>
        private void CheckConnectThread()
        {
            Task.Run(async () =>
            {
                while (true)
                {
                    try
                    {
                        await Task.Run(() =>
                        {
                            lock (_lock)
                            {
                                // 判断连接状态
                                if (_host != null && _needToReconnect && _mqttClient?.IsConnected != true)
                                {
                                    // 重新连接
                                    ConnectAsync().Wait();
                                    // 订阅主题
                                    SubscribeAsync(_topics).Wait();
                                }
                            }
                        });
                    }
                    catch (Exception ex)
                    {
                        _logger?.LogError(ex, "MQTT判断连接状态的线程报错");
                    }
                    await Task.Delay(1000);
                }
            });
        }
    }
}
View Code

 

posted @ 2024-04-02 09:47  Mr_Xul  阅读(71)  评论(0编辑  收藏  举报