فهرست منبع

V2.4
1、MQTT新增了手动超时连接,使用定时器定期连接

Apple 1 هفته پیش
والد
کامیت
30fa46ee93

+ 4 - 4
TransmitterSwitch/Network/FromMQTT.cpp

@@ -40,13 +40,13 @@ bool FromMQTT::initMQTT()
     /* 连接MQTT */
     setIPAndPort(m_mqttIP, m_mqttPort);
     addSubcribe(m_topic_WebAPI, 0); // 订阅WebAPI主题
+    addSubcribe(m_topic_UpdatePlan); // 订阅更新计划主题
+    /* 设置自动重连 */
+    setAutoReconnect(true);
     if(!m_client.isConnectedToHost())
     {
         connectToServer();
     }
-    /* 设置自动重连 */
-    setAutoReconnect();
-
     /* 等待mqtt回复webapi信息(不阻塞UI,收到立即退出)*/
     waitForWebInfo(m_timeOut);
 
@@ -59,7 +59,7 @@ bool FromMQTT::initMQTT()
     }
 
     /* 开启MQTT订阅 */
-    addSubcribe(m_topic_UpdatePlan);
+    // addSubcribe(m_topic_UpdatePlan);
 
     return true;
 }

+ 46 - 4
TransmitterSwitch/common/qmqtt/mqttBase/MQTTBase.cpp

@@ -17,6 +17,9 @@ MQTTBase::MQTTBase(QObject* parent) : QObject(parent)
     //     exit(-1);
     // }
 
+    // m_client.setKeepAlive(2); // 设置心跳时间为5秒
+    m_reconnectTimer.setSingleShot(false);
+
     /* 连接信号和槽 */
     connect(&m_client,SIGNAL(connected()),this,SLOT(do_connected()));
     connect(&m_client,SIGNAL(disconnected()),this,SLOT(do_disconnect()));
@@ -25,6 +28,7 @@ MQTTBase::MQTTBase(QObject* parent) : QObject(parent)
 
     connect(&m_client,SIGNAL(received(QMQTT::Message)),this,SLOT(do_received(QMQTT::Message)));
     connect(&m_client, &QMQTT::Client::received, this, &MQTTBase::signal_recvMessage);
+    connect(&m_reconnectTimer, &QTimer::timeout, this, &MQTTBase::do_timeoutReconnect);
 }
 
 /* 设置地址 */
@@ -45,7 +49,7 @@ void MQTTBase::addSubcribe(const QString& topic, int qos)
         SPDLOG_ERROR("QoS值不合法:{}", qos);
         return;
     }
-    if(m_isConnected)
+    if(m_client.connectionState() == QMQTT::ConnectionState::STATE_CONNECTED)
     {
         /* 已连接到MQTT,之前添加的主题已经订阅,现在添加的也直接添加订阅 */
         m_client.subscribe(topic, qos);
@@ -60,12 +64,23 @@ void MQTTBase::addSubcribe(const QString& topic, int qos)
 /* 设置自动重连 */
 void MQTTBase::setAutoReconnect(bool isAuto)
 {
+    m_isAutoReconnect = isAuto;
     m_client.setAutoReconnect(isAuto);
 }
 
 /* 连接到服务器 */
 void MQTTBase::connectToServer()
 {
+    if(m_client.connectionState() == QMQTT::ConnectionState::STATE_CONNECTED)
+    {
+        SPDLOG_INFO("MQTT已经连接到服务器,无需重复连接");
+        return;
+    }
+    else if(m_client.connectionState() == QMQTT::ConnectionState::STATE_CONNECTING)
+    {
+        SPDLOG_INFO("MQTT正在连接到服务器,请稍后");
+        return;
+    }
     m_client.connectToHost();
 }
 
@@ -78,7 +93,7 @@ QMQTT::ConnectionState MQTTBase::connectState()
 /* 发送消息 */
 bool MQTTBase::sendMessage(const QString& topic, const QByteArray& message, int qos)
 {
-    if(m_isConnected == false)
+    if(m_client.connectionState() != QMQTT::ConnectionState::STATE_CONNECTED)
     {
         SPDLOG_ERROR("MQTT未连接到服务器,发送消息失败");
         return false;
@@ -97,7 +112,7 @@ bool MQTTBase::sendMessage(const QString& topic, const QByteArray& message, int
 /* 发送消息,设置消息保留 */
 bool MQTTBase::sendMessage(const QString& topic, const QByteArray& message, int qos, bool retain)
 {
-    if(m_isConnected == false)
+    if(m_client.connectionState() != QMQTT::ConnectionState::STATE_CONNECTED)
     {
         SPDLOG_ERROR("MQTT未连接到服务器,发送消息失败");
         return false;
@@ -123,7 +138,10 @@ bool MQTTBase::sendMessage(const QString& topic, const QByteArray& message, int
 void MQTTBase::do_connected()
 {
     SPDLOG_INFO("MQTT IP:{} ,Port:{} 连接成功!", m_mqttIP.toStdString(), m_mqttPort);
-    m_isConnected = true;
+    if(m_reconnectTimer.isActive())
+    {
+        m_reconnectTimer.stop();
+    }
     /* 订阅所有的主题 */
     for(auto& it : m_mapTopic.keys())
     {
@@ -136,12 +154,29 @@ void MQTTBase::do_connected()
 void MQTTBase::do_disconnect()
 {
     SPDLOG_INFO("MQTT 断开连接!");
+    if(m_isAutoReconnect)
+    {
+        SPDLOG_INFO("MQTT 自动重连已开启,正在尝试重新连接...");
+        if(m_reconnectTimer.isActive())
+        {
+            m_reconnectTimer.stop();
+        }
+        m_reconnectTimer.start(6000);
+        connectToServer();
+    }
+    emit signal_disconnected();
+    // m_isConnected = false;
 }
 
 /* 错误 */
 void MQTTBase::do_error(const QMQTT::ClientError error)
 {
     SPDLOG_ERROR("MQTT 错误:{}", (int)error);
+    // if(m_isAutoReconnect)
+    // {
+    //     SPDLOG_INFO("MQTT 自动重连已开启,正在尝试重新连接...");
+    //     m_client.connectToHost();
+    // }
 }
 
 /* 订阅成功 */
@@ -157,3 +192,10 @@ void MQTTBase::do_received(const QMQTT::Message& message)
     recvMessage(message);
 }
 
+/* 超时重连 */
+void MQTTBase::do_timeoutReconnect()
+{
+    SPDLOG_INFO("MQTT 超时重连...");
+    connectToServer();
+}
+

+ 8 - 4
TransmitterSwitch/common/qmqtt/mqttBase/MQTTBase.h

@@ -4,6 +4,7 @@
 #include <QObject>
 #include <QMap>
 #include <QChar>
+#include <QTimer>
 
 #include "qmqtt.h"
 
@@ -54,10 +55,10 @@ public:
     
     
 signals:
-    /* 接收到消息,对消息进行了转发 */
-    // void signal_recvMessage(const QString& message);
     /* 原地转发消息 */
     void signal_recvMessage(const QMQTT::Message& message);
+    /* 断开连接的信号 */
+    void signal_disconnected();
 
 protected:
     /* 接收到消息,子类继承这个解析消息数据 */
@@ -71,15 +72,18 @@ protected slots:
 
     void do_received(const QMQTT::Message& message);/* 接收到消息,子类继承这个解析消息数据 */
 
+    /* 超时重连 */
+    void do_timeoutReconnect();
+    
 
 protected:
-    // std::shared_ptr<spdlog::logger> m_logger = nullptr;
-    bool m_isConnected = false;                     /* 是否连接成功 */
+    bool m_isAutoReconnect = true;                  /* 是否自动重连 */
     QString m_mqttIP;                               /* MQTT服务器IP */
     int m_mqttPort;                                 /* MQTT服务器端口 */
 
     QMap<QString, int> m_mapTopic;                  /* 订阅的主题和QOS */
     QMQTT::Client m_client;                         /* MQTT客户端 */
+    QTimer m_reconnectTimer;                        /* 重连定时器 */
 };
 
 

+ 20 - 1
TransmitterSwitch/transmitterswitch.cpp

@@ -121,14 +121,16 @@ TransmitterSwitch::~TransmitterSwitch()
 /* 初始化webAPI,重载版 */
 void TransmitterSwitch::initTS(const InitData& data)
 {
+    m_initData = data;
     if(data.userPermission == static_cast<int>(eUserPermission::User_IsESM8C))
     {
         /* ESM8C上位机使用MQTT方式获取WebAPI信息 */
         m_fromMQTT.setAddrInfo(data.url, data.serverID.toInt());
     }
+    // connect(&m_fromMQTT, &FromMQTT::signal_webInfoReady, this, &TransmitterSwitch::do_initWebAPI);
     m_fromMQTT.initMQTT();
     // setWebAPIInfo(data.url, data.serverID, data.serverKey);
-    setWebAPIInfo(m_fromMQTT.m_webAPIUrl, m_fromMQTT.m_webAPIID, data.serverKey);
+    setWebAPIInfo(m_fromMQTT.m_webAPIUrl, m_fromMQTT.m_webAPIID, m_initData.serverKey);
     /* 设置权限 */
     // setUserPermission(data.userPermission);
     setUserPermission(1);
@@ -215,6 +217,8 @@ void TransmitterSwitch::setWebAPIInfo(const QString &url, const QString &serverI
 
     /* 创建获取到的卡片信息 */
     createAllCard();
+    /* 刷新页面 */
+    update();
 }
 
 
@@ -725,6 +729,21 @@ void TransmitterSwitch::do_pBtnAddExecPlan()
     }
 }
 
+
+/* MQTT消息槽函数 */
+// void TransmitterSwitch::do_initWebAPI()
+// {
+//     SPDLOG_INFO("WebAPI URL: {}", m_fromMQTT.m_webAPIUrl.toStdString());
+//     SPDLOG_INFO("WebAPI DBID: {}", m_fromMQTT.m_webAPIID.toStdString());
+//     if(m_fromMQTT.m_webAPIUrl.isEmpty())
+//     {
+//         SPDLOG_ERROR("接收MQTT消息超时,获取WebAPI信息失败");
+//         return;
+//     }
+//     setWebAPIInfo(m_fromMQTT.m_webAPIUrl, m_fromMQTT.m_webAPIID, m_initData.serverKey);
+// }
+
+
 /* 点击了修改按钮 */
 void TransmitterSwitch::do_pBtnModifyExecPlan()
 {

+ 3 - 1
TransmitterSwitch/transmitterswitch.h

@@ -70,7 +70,8 @@ public:
     void setOnePlanData(QList<OnePlanItemInfo>& listPlan, ExecPlanConfig& config, int channelID = 0);
 
 private slots:
-
+    /* MQTT消息槽函数 */
+    // void do_initWebAPI();
     /* 点击了添加计划按钮 */
     void do_pBtnAddExecPlan();
     /* 点击了修改按钮 */
@@ -164,6 +165,7 @@ protected:
 private:
     Ui::TransmitterSwitch *ui;
 
+    InitData m_initData;               /* 初始化数据 */
     QLabel* m_tipText = nullptr;            /* 提示文本 */
     QString m_styleSheet;                   /* 样式表 */