Mqttnet实现的mqtt客户端

using System.Collections.Concurrent;
using System.Text;
using MQTTnet;
using MQTTnet.Client;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Logging;
using MQTTnet.Server;
using Microsoft.Extensions.Hosting;
using System.Net.NetworkInformation;
using Serilog.Core;
using Serilog;
using Huahuan.CollectorServiceCore.Methods;
using Huahuan.CollectorServiceCore.Models;
using Huahuan.CollectorServiceCore.SqlSugar.Methods;
using Huahuan.CollectorServiceCore.Protocols;
using Huahuan.CollectorServiceCore.SqlSugar.Models;
using Huahuan.CollectorServiceCore.Services;
using Microsoft.VisualBasic;
using System.Text.Json.Nodes;
using Huahuan.CommonLib.Methods;

namespace Huahuan.CollectorServiceCore
{
    public class MqttHuahuan
    {
        private static readonly Logger _logger;

        //private readonly ConcurrentDictionary<long, string> dicReply = new(); // 消息id,消息
        private static ConcurrentQueue<MqttMesssage> queuePubMsg = new();
        private static ConcurrentQueue<MqttMesssage> queueSubMsg = new();
        private static IMqttClient? mqttClient;
        private static MqttClientOptions? mqttClientOptions;
        private static bool isLongConnect = false;// 长连接

        private static ConcurrentDictionary<string, UInt32> dicCollectorFilter = new ConcurrentDictionary<string, UInt32>(); // 采集器管理


        static MqttHuahuan()
        {
            _logger = new LoggerConfiguration()
                .WriteTo.File($"{AppDomain.CurrentDomain.BaseDirectory}/logs/MqttHuahuan-.txt", rollingInterval: RollingInterval.Day) // 按天写入文件 
                .CreateLogger();

            ConcurrentDictionary<string, UInt32> dic31311 = CollectorTB.GetSnCycleByPort(31311); // 获取采集器
            ConcurrentDictionary<string, UInt32> dic55888 = CollectorTB.GetSnCycleByPort(55888); // 获取采集器
            dicCollectorFilter = dic31311;
            foreach (var kv in dic55888)
            {
                dicCollectorFilter.TryAdd(kv.Key, kv.Value);
            }
            _ = ClientCreate();
        }
        public static async Task ClientCreate()
        {
            do
            {
                try
                {
                    var mqttParams = AppConfigHelper.GetMqttOptions(); // 获取配置
                    var mqttFactory = new MqttFactory();
                    mqttClient = mqttFactory.CreateMqttClient();
                    mqttClientOptions = new MqttClientOptionsBuilder()
                        .WithTcpServer(mqttParams.Host, mqttParams.Port)
                        .WithClientId(mqttParams.ClientId)
                        .WithCredentials(mqttParams.User, mqttParams.Password)
                        .WithCleanSession(false)
                        .WithKeepAlivePeriod(TimeSpan.FromSeconds(60)) // 设置 Keep Alive 间隔为 60 秒。
                        .WithCleanSession(true)
                        .Build();

                    // 连接断开事件
                    mqttClient.DisconnectedAsync += async e =>
                    {
                        if (isLongConnect)
                        {
                            await Task.Delay(5000);
                            _logger.Information("MqttHuahuan:发起重连");
                            await Start();
                        }
                    };
                    // 订阅事件
                    mqttClient.ApplicationMessageReceivedAsync += e =>
                    {
                        //Log.LogInformation($"Received message: {Encoding.UTF8.GetString(e.ApplicationMessage.PayloadSegment)}");
                        MqttMesssage mqttMesssage = new()
                        {
                            Topic = e.ApplicationMessage.Topic,
                            Message = Encoding.UTF8.GetString(e.ApplicationMessage.PayloadSegment)
                        };
                        queueSubMsg.Enqueue(mqttMesssage);
                        return Task.CompletedTask;
                    };
                    // 连接成功事件
                    mqttClient.ConnectedAsync += async e =>
                    {
                        _logger.Information("MqttHuahuan:连接成功");
                        await mqttClient.UnsubscribeAsync("#");

                        // 添加订阅逻辑
                        //var mqttParams = AppConfigHelper.GetMqttOptions();
                        if (mqttParams.SubTopics != null)
                        {
                            foreach (var topic in mqttParams.SubTopics)
                            {
                                await mqttClient.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic(topic).Build());
                            }
                        }
                    };

                    Task taskSub = new(action: async () => await SubscribeMessageProcessTask());
                    taskSub.Start();
                    Task taskPub = new(action: async () => await PublishMessagePorcessAsync());
                    taskPub.Start();

                    //Task testTask = new Task(action: async () => await PublishMessageTest());
                    //testTask.Start();
                }
                catch (Exception e)
                {
                    _logger.Error("MqttHuahuan:创建失败,{e}", e.Message);
                    await Task.Delay(5000);
                }
            } while (mqttClient == null);
        }

        public static async Task Start()
        {
            try
            {
                isLongConnect = true;
                if (mqttClient != null)
                {
                    var response = await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
                }
                else
                {
                    _logger.Information("mqttClient is null");
                }
            }
            catch (Exception e)
            {
                _logger.Error("MqttHuahuan:连接失败,{e}", e.Message);
            }
        }
        public static async Task Stop()
        {
            isLongConnect = false;
            if (mqttClient != null && mqttClient.IsConnected)
            {
                await mqttClient.DisconnectAsync();
            }
            _logger.Information("MqttHuahuan:已退出");
        }


        private static async Task PublishMessageTest()
        {
            await Task.Delay(5000);
            while (isLongConnect)
            { 
                MqttMesssage msg = new MqttMesssage();
                msg.Retain = false;
                msg.Topic = "utest/123";
                msg.Message = "test1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111";
                queuePubMsg.Enqueue(msg);
                await Task.Delay(1);
            }
        }

        /// <summary>
        /// 发布消息任务
        /// </summary>
        private static async Task PublishMessagePorcessAsync()
        {
            await Task.Delay(2000);
            int dly = 1000;
            _logger.Information("MqttHuahuan:发布消息任务已启动");
            while (isLongConnect)
            {
                try
                {
                    if (mqttClient != null && mqttClient.IsConnected)
                    {
                        if (!queuePubMsg.IsEmpty)
                        {
                            if (queuePubMsg.TryDequeue(out MqttMesssage? pub_msg))
                            {
                                if (pub_msg == null) continue;
                                if (string.IsNullOrWhiteSpace(pub_msg.Topic)) continue;
                                if (string.IsNullOrWhiteSpace(pub_msg.Message)) continue;
                                MqttApplicationMessage message = new()
                                {
                                    PayloadSegment = Encoding.UTF8.GetBytes(pub_msg.Message),
                                    Topic = pub_msg.Topic,
                                    Retain = pub_msg.Retain,
                                    QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce
                                };
                                //_logger.Information("发布消息:topic={topic},payload={payload}",pub_msg.Topic, pub_msg.Message);

                                await mqttClient.PublishAsync(message);
                            }
                            //await Task.Delay(1);
                        }
                        else
                        {
                            await Task.Delay(1000);
                        }
                    }
                    else
                    {
                        _logger.Warning("MqttHuahuan,发布任务,mqttc is null or disconneted!");
                        await Task.Delay(10000);
                    }
                    dly = 1000;
                }
                catch (Exception e)
                {
                    _logger.Error("MqttHuahuan:发布消息异常:{e}", e.Message);
                    await Task.Delay(dly);
                    if (dly < 60000) // 1分钟
                    {
                        dly += dly;
                    }
                }
            }
            _logger.Information("MqttHuahuan:发布消息任务已停止");
        }

        /// <summary>
        /// 订阅消息处理任务
        /// </summary>
        private static async Task SubscribeMessageProcessTask()
        {
            await Task.Delay(2000);
            int dly = 1000;
            _logger.Information("MqttHuahuan:订阅消息任务已启动");
            while (isLongConnect)
            {
                try
                {
                    if (queueSubMsg.TryDequeue(out MqttMesssage? sub_msg))
                    {
                        if (sub_msg == null) continue;
                        if (string.IsNullOrWhiteSpace(sub_msg.Topic)) continue;
                        if (string.IsNullOrWhiteSpace(sub_msg.Message)) continue;
                        string[] splitTopics = sub_msg.Topic.Split('/');
                        string payload = sub_msg.Message;

                        if (splitTopics.Length > 4)
                        {
                            string sn = splitTopics[4];
                            string model = splitTopics[3];
                            if (splitTopics[1] == "up")
                            {
                                if (splitTopics[2] == "sensors")
                                {
                                    Log.Information("传感器数据, topic={0}, payload={1}", sub_msg.Topic, sub_msg.Message);
                                    // 过滤器
                                    if (AppConfigHelper.GetOtherOptions().DataFilterUsed)
                                    {
                                        if (!dicCollectorFilter.ContainsKey(sn)) // 过滤未添加的采集器
                                        {
                                            _logger.Information("【拦截】topic={0},payload={1}" , sub_msg.Topic, sub_msg.Message); // 记录被过滤的数据
                                            continue;
                                        }
                                    }
                                    //List<SensorData>? list = CollectorJsonProto.ToSensorData(sn, payload);
                                    List<SensorData>? list = CollectorJsonProto.ToSensorDataPluse(sn, payload);
                                    if (list!=null)
                                    {
                                        foreach (SensorData sd in list) DataService.AddSensorData(sd);
                                    }
                                    else
                                    {
                                        _logger.Error("传感器数据解析失败!topic={0},payload={1}", sub_msg.Topic, sub_msg.Message);
                                    }
                                }
                                else if (splitTopics[2] == "collectors")
                                {
                                    //if (strings[3] == "HD_CJY2021_724") // 转发
                                    //{
                                    //    sub_msg.Topic.Replace("shhhcl", "yun");
                                    //    sub_msg.Topic.Replace("HD_CJY2021_724", "HD-CJY2021");
                                    //    AddToQueuePubMsg(sub_msg);
                                    //}

                                    // 过滤器
                                    if (AppConfigHelper.GetOtherOptions().DataFilterUsed)
                                    {
                                        if (!dicCollectorFilter.ContainsKey(sn)) // 过滤未添加的采集器
                                        {
                                            _logger.Information("【拦截】topic={0},payload={1}", sub_msg.Topic, sub_msg.Message); // 记录被过滤的数据
                                            continue;
                                        }
                                    }
                                    JsonObject? jo = JsonHepler.FromJson<JsonObject>(payload);
                                    string? msgtype = (string?)jo?["msgtype"];
                                    if (string.IsNullOrWhiteSpace(msgtype)) continue;
                                    if ((jo?["message"] == null)) continue;
                                    if ((msgtype == "collector_datas") || (msgtype == "node_datas"))
                                    {
                                        CollectorData? cd = CollectorJsonProto.ToColletorData(sn, model, jo["message"]?.ToString());
                                        if (cd != null)
                                        {
                                            DataService.AddCollectorData(cd);
                                        }
                                        else
                                        {
                                            _logger.Error("采集仪数据解析失败!topic={0},payload={1}", sub_msg.Topic, sub_msg.Message);
                                        }
                                    }
                                    else if (msgtype == "collector_event")
                                    {

                                    }
                                }
                            }
                        }
                        else if (splitTopics.Length == 4)
                        {
                            if (splitTopics[1] == "request")
                            {
                                string msgid = splitTopics[3]; // 消息id
                                string method = splitTopics[2]; // 方法
                                
                                switch (method)
                                {
                                    case "add_collector":
                                        new ApiMqttProtoService(_logger).AddCollector(msgid, payload);
                                        break;
                                    case "del_collector":
                                        new ApiMqttProtoService(_logger).DelCollector(msgid, payload);
                                        break;
                                    case "mod_collector":
                                        new ApiMqttProtoService(_logger).ModCollector(msgid, payload);
                                        break;
                                    case "set_sensors":
                                        new ApiMqttProtoService(_logger).SetSensorList(msgid, payload);
                                        break;
                                    case "set_wx_sensors":

                                        break;
                                    case "restart_collector":
                                        new ApiMqttProtoService(_logger).RestartCollector(msgid, payload);
                                        break;
                                    case "ser_server":
                                        new ApiMqttProtoService(_logger).SetServer(msgid, payload);
                                        break;
                                    default:
                                        _logger.Information("不需要处理的方法,{fn}", method);
                                        break;
                                }
                            }

                        }
                        else if (splitTopics.Length == 2) // 节点事件
                        {
                            string[] arr = payload.Split('_');
                            string sn = "";
                            bool isConnected = false;
                            if (arr.Length != 1) continue; // 消息错误
                            sn = arr[arr.Length - 1]; // 编号
                            if (sn.Substring(0, 2) != "86")
                            {
                                //_logger.Warning("MqttHuahuan:设备编号不匹配, sn={sn}", sn); // 编号不匹配
                                continue; // 不是设备编号
                            }
                            if (AppConfigHelper.GetOtherOptions().DataFilterUsed)
                            {
                                if (!dicCollectorFilter.ContainsKey(sn)) // 过滤未添加的采集器
                                    continue;
                            }
                            if (splitTopics[1] == "client_connected") // 上线
                            {
                                isConnected = true;
                            }
                            else if (splitTopics[1] == "client_disconnected") // 离线
                            {
                                isConnected = false;
                            }
                            DataService.AddCollectorSataus(new CollectorStatus() { Sn = sn, Status = isConnected, Created = DateTime.Now }); // 修改采集仪连接状态
                            if (AppConfigHelper.GetOtherOptions().TcpToMqttAllowed) // 转发
                            {
                                PublishMessage(CollectorJsonProto.StatusConvert(sn, isConnected));
                            }

                        }
                        await Task.Delay(1);
                    }
                    else
                    {
                        await Task.Delay(1000);
                    }
                    dly = 1000;
                }
                catch (Exception e)
                {
                    _logger.Error("MqttHuahuan:消息处理异常:{e}", e.Message);
                    await Task.Delay(dly);
                    if (dly < 60000) // 1分钟
                    {
                        dly += dly;
                    }
                }
            }
            _logger.Information("MqttHuahuan:订阅消息任务已停止");
        }
        /// <summary>
        /// 添加要发布的消息
        /// </summary>
        /// <param name="mqttMesssage"></param>
        public static void PublishMessage(MqttMesssage mqttMesssage)
        {
            queuePubMsg.Enqueue(mqttMesssage);
        }

        /// <summary>
        /// 移除采集器
        /// </summary>
        /// <param name="sn"></param>
        /// <returns></returns>
        public static Boolean CollectorRemove(string sn)
        {
            if (dicCollectorFilter.TryRemove(sn, out _))
            {
                return true;
            }
            return false;
        }
        /// <summary>
        /// 添加采集器
        /// </summary>
        /// <param name="sn"></param>
        /// <param name="cycle"></param>
        /// <returns></returns>
        public static Boolean CollectorAdd(string sn, UInt32 cycle)
        {
            if (dicCollectorFilter.TryAdd(sn, cycle))
            {
                return true;
            }
            return false;
        }

    }
}

 

posted @ 2024-08-14 09:24  曾锋  阅读(66)  评论(0)    收藏  举报