wangming преди 1 месец
родител
ревизия
c20ab9c813
променени са 3 файла, в които са добавени 181 реда и са изтрити 130 реда
  1. 19 3
      src/main.js
  2. 17 0
      src/pages/home/home.vue
  3. 145 127
      src/utils/globalMqtt.js

+ 19 - 3
src/main.js

@@ -17,13 +17,29 @@ Vue.prototype.$http = http;
 
 // 全局方法:初始化 MQTT(登录成功时调用)
 Vue.prototype.$initMqtt = function () {
-    const userId = uni.getStorageSync("userId")
+    const userId = uni.getStorageSync("userId");
     if (!userId) {
-        console.warn("MQTT 初始化失败:缺少 userId")
-        return
+        console.warn("MQTT 初始化失败:缺少 userId");
+        return;
     }
+
+    // 连接 CMD
     MqttService.connectCmd(userId)
+        .then(client => {
+            console.log("CMD MQTT 初始化完成", client);
+        })
+        .catch(err => {
+            console.error("CMD MQTT 初始化失败", err);
+        });
+
+    // 连接 DATA
     MqttService.connectData(userId)
+        .then(client => {
+            console.log("DATA MQTT 初始化完成", client);
+        })
+        .catch(err => {
+            console.error("DATA MQTT 初始化失败", err);
+        });
 }
 
 

+ 17 - 0
src/pages/home/home.vue

@@ -554,6 +554,23 @@ export default {
     height: 28rpx;
 }
 
+.bottom button {
+    all: unset;
+    margin: 0;
+    padding: 0;
+    border: none;
+    background: none;
+    font: inherit;
+    text-align: inherit;
+    line-height: normal;
+    outline: none;
+    box-shadow: none;
+    -webkit-appearance: none;
+    margin-left: 6rpx;
+    color: #a1aab4;
+    font-size: 28rpx;
+}
+
 .bot_version {
     opacity: 0.4;
     position: absolute;

+ 145 - 127
src/utils/globalMqtt.js

@@ -1,164 +1,182 @@
-// mqttService.js
-import mqtt from './mqtt'
+import mqtt from './mqtt.js';
 
 class MqttService {
     constructor() {
         if (!MqttService.instance) {
-            this.cmdClient = null
-            this.dataClient = null
-            this.cmdConnected = false
-            this.dataConnected = false
-            MqttService.instance = this
+            this.cmdClient = null;
+            this.dataClient = null;
+            this.cmdConnected = false;
+            this.dataConnected = false;
+            this.connections = new Map(); // 内部管理多连接
+            MqttService.instance = this;
         }
-        return MqttService.instance
+        return MqttService.instance;
     }
 
     // 连接 CMD
     connectCmd(userId) {
         if (this.cmdConnected && this.cmdClient) {
-            console.log("CMD MQTT 已连接,复用现有实例")
-            return this.cmdClient
-        }
-        console.log("CMD MQTT 连接中...")
-        const params = {
-            clientId: "xcx_mqtt_cmd1_" + userId + "_" + Math.random().toString(16).substring(2, 8),
-            username: "lnradar",
-            password: "lnradar",
-            wsOptions: {
-                WebSocket: function (url) {
-                    return wx.connectSocket({
-                        url,
-                        header: { "content-type": "application/json" },
-                        protocols: ["mqtt"],
-                    })
-                },
-            },
+            console.log("CMD MQTT 已连接,复用现有实例");
+            return Promise.resolve(this.cmdClient);
         }
 
-        this.cmdClient = mqtt.connect("wxs://cmd.radar-power.cn/mqtt/", params)
-
-        this.cmdClient.on("connect", () => {
-            this.cmdConnected = true
-            console.log("CMD MQTT 连接成功")
-            uni.$emit("mqtt-ready", this.cmdClient)
-            this.cmdClient.subscribe(`/mps/wx_${userId}/notice`, (err) => {
-                if (err) {
-                    console.error("CMD 订阅失败", err)
-                } else {
-                    console.log(`成功订阅设备主题: /mps/wx_${userId}/notice`)
-                }
-            })
-        })
-
-        this.cmdClient.on("message", (topic, message) => {
-            console.log("CMD 接收到消息:", topic, JSON.parse(message.toString()))
-        })
+        const brokerName = 'CMD';
+        const url = 'wxs://cmd.radar-power.cn/mqtt/';
+        const clientId = `xcx_mqtt_cmd1_${userId}_${Math.random().toString(16).substring(2, 8)}`;
 
-        this.cmdClient.on("error", (err) => {
-            this.cmdConnected = false
-            console.error("CMD MQTT 连接错误:", err)
-        })
+        return this.connectToBroker(brokerName, { url, clientId, username: 'lnradar', password: 'lnradar' })
+            .then(client => {
+                this.cmdClient = client;
+                this.cmdConnected = true;
 
-        this.cmdClient.on("disconnect", () => {
-            this.cmdConnected = false
-            console.log("CMD MQTT 断开")
-        })
+                // 默认订阅 CMD 主题
+                this.subscribe('CMD', `/mps/wx_${userId}/notice`, (msg) => {
+                    console.log('CMD 消息:', msg);
+                });
 
-        return this.cmdClient
+                uni.$emit('mqtt-ready', this.cmdClient);
+                return client;
+            });
     }
 
     // 连接 DATA
     connectData(userId) {
         if (this.dataConnected && this.dataClient) {
-            console.log("DATA MQTT 已连接,复用现有实例")
-            return this.dataClient
-        }
-        console.log("DATA MQTT 连接中...")
-        const params = {
-            clientId: "xcx_mqtt_data1_" + userId + "_" + Date.now(),
-            username: "lnradar",
-            password: "lnradar",
-            WebSocket: function (url) {
-                return wx.connectSocket({
-                    url,
-                    header: { "content-type": "application/json" },
-                    protocols: ["mqtt"],
-                })
-            },
+            console.log("DATA MQTT 已连接,复用现有实例");
+            return Promise.resolve(this.dataClient);
         }
 
-        this.dataClient = mqtt.connect("wxs://data.radar-power.cn/mqtt/", params)
-
-        this.dataClient.on("connect", () => {
-            this.dataConnected = true
-            uni.$emit("mqttData-ready", this.dataClient)
-            console.log("DATA MQTT 连接成功")
-        })
-
-        this.dataClient.on("message", (topic, message) => {
-            console.log("DATA 接收到消息:", topic, JSON.parse(message.toString()))
-        })
-
-        this.dataClient.on("error", (err) => {
-            this.dataConnected = false
-            console.error("DATA MQTT 连接错误:", err)
-        })
-
-        this.dataClient.on("disconnect", () => {
-            this.dataConnected = false
-            console.log("DATA MQTT 断开")
-        })
-
-        // 给 DATA 加一个关闭方法
-        this.dataClient.close = (force = true) => {
-            this.dataClient.end(force, () => {
-                this.dataConnected = false
-                this.dataClient = null
-                console.log("DATA MQTT 已关闭")
-            })
-        }
+        const brokerName = 'DATA';
+        const url = 'wxs://data.radar-power.cn/mqtt/';
+        const clientId = `xcx_mqtt_data1_${userId}_${Date.now()}`;
+
+        return this.connectToBroker(brokerName, { url, clientId, username: 'lnradar', password: 'lnradar' })
+            .then(client => {
+                this.dataClient = client;
+                this.dataConnected = true;
 
-        return this.dataClient
+                uni.$emit('mqttData-ready', this.dataClient);
+                return client;
+            });
     }
 
-    // 发布
+    // 内部通用连接方法(多连接管理)
+    connectToBroker(brokerName, config) {
+        return new Promise((resolve, reject) => {
+            if (this.connections.has(brokerName)) {
+                const existingConn = this.connections.get(brokerName);
+                if (existingConn.connected) {
+                    resolve(existingConn.client);
+                    return;
+                }
+            }
+
+            const client = mqtt.connect(config.url, {
+                clientId: config.clientId,
+                username: config.username,
+                password: config.password,
+                reconnectPeriod: config.reconnectPeriod || 5000,
+                wsOptions: {
+                    WebSocket: url => wx.connectSocket({
+                        url,
+                        header: { 'content-type': 'application/json' },
+                        protocols: ['mqtt'],
+                    })
+                },
+            });
+
+            const connection = {
+                client,
+                connected: false,
+                subscriptions: new Map(),
+            };
+            this.connections.set(brokerName, connection);
+
+            client.on('connect', () => {
+                console.log(`${brokerName} MQTT 连接成功`);
+                connection.connected = true;
+                resolve(client);
+            });
+
+            client.on('error', (err) => {
+                console.error(`${brokerName} MQTT 连接错误:`, err);
+                connection.connected = false;
+                reject(err);
+            });
+
+            client.on('close', () => {
+                console.log(`${brokerName} MQTT 断开`);
+                connection.connected = false;
+            });
+
+            client.on('message', (topic, message) => {
+                const callbacks = connection.subscriptions.get(topic) || [];
+                callbacks.forEach(cb => {
+                    try { cb(message.toString(), topic, brokerName); }
+                    catch (err) { console.error('Message callback error:', err); }
+                });
+            });
+
+            // 连接超时
+            setTimeout(() => {
+                if (!connection.connected) reject(new Error(`${brokerName} 连接超时`));
+            }, 10000);
+        });
+    }
+
+    // 发布消息
     publish(clientType, topic, message) {
-        const client = clientType === "CMD" ? this.cmdClient : this.dataClient
-        if (client) {
-            client.publish(topic, message)
-        } else {
-            console.warn(`${clientType} MQTT 未连接,无法 publish`)
-        }
+        const client = clientType === 'CMD' ? this.cmdClient : this.dataClient;
+        if (client) client.publish(topic, message);
+        else console.warn(`${clientType} MQTT 未连接,无法 publish`);
     }
 
     // 订阅
-    subscribe(clientType, topic) {
-        const client = clientType === "CMD" ? this.cmdClient : this.dataClient
-        if (client) {
-            client.subscribe(topic)
-        } else {
-            console.warn(`${clientType} MQTT 未连接,无法 subscribe`)
+    subscribe(clientType, topic, callback) {
+        const connection = clientType === 'CMD' ? this.connections.get('CMD') : this.connections.get('DATA');
+        if (!connection || !connection.connected) {
+            console.warn(`${clientType} MQTT 未连接,无法 subscribe`);
+            return;
+        }
+
+        if (!connection.subscriptions.has(topic)) connection.subscriptions.set(topic, []);
+        const callbacks = connection.subscriptions.get(topic);
+        if (!callbacks.includes(callback)) callbacks.push(callback);
+
+        connection.client.subscribe(topic, err => {
+            if (err) console.error(`Subscribe error on ${clientType}:`, err);
+        });
+
+        // 返回取消订阅函数
+        return () => this.unsubscribe(clientType, topic, callback);
+    }
+
+    // 取消订阅
+    unsubscribe(clientType, topic, callback) {
+        const connection = clientType === 'CMD' ? this.connections.get('CMD') : this.connections.get('DATA');
+        if (!connection) return;
+
+        const callbacks = connection.subscriptions.get(topic);
+        if (callbacks) {
+            const index = callbacks.indexOf(callback);
+            if (index > -1) callbacks.splice(index, 1);
+            if (callbacks.length === 0) {
+                connection.subscriptions.delete(topic);
+                connection.client.unsubscribe(topic);
+            }
         }
     }
 
     // 断开所有连接
     disconnectAll() {
-        if (this.cmdClient) {
-            this.cmdClient.end(true)
-            this.cmdClient = null
-            this.cmdConnected = false
-            console.log("CMD MQTT 已关闭")
-        }
-        if (this.dataClient) {
-            this.dataClient.end(true)
-            this.dataClient = null
-            this.dataConnected = false
-            console.log("DATA MQTT 已关闭")
-        }
+        if (this.cmdClient) { this.cmdClient.end(true); this.cmdClient = null; this.cmdConnected = false; }
+        if (this.dataClient) { this.dataClient.end(true); this.dataClient = null; this.dataConnected = false; }
+        this.connections.forEach(conn => conn.client.end());
+        this.connections.clear();
+        console.log('所有 MQTT 连接已关闭');
     }
 }
 
-const instance = new MqttService()
-// Object.freeze(instance)
-
-export default instance
+// 单例导出
+const instance = new MqttService();
+export default instance;