|
|
@@ -0,0 +1,136 @@
|
|
|
+// src/plugins/mqttPlugins.js
|
|
|
+// ✅ 正确方式:使用浏览器兼容版本
|
|
|
+import mqtt from "mqtt";
|
|
|
+import { Message } from "element-ui"; // 或你用的 UI 库,用于提示
|
|
|
+
|
|
|
+const MQTT_URL = "ws://your-mqtt-broker:8083"; // 替换为你的 MQTT Broker WebSocket 地址
|
|
|
+const OPTIONS = {
|
|
|
+ clientId: "vue-client-" + Math.random().toString(16).substr(2, 8),
|
|
|
+ username: "your-username", // 如果需要认证
|
|
|
+ password: "your-password", // 如果需要认证
|
|
|
+ clean: true,
|
|
|
+ connectTimeout: 30000,
|
|
|
+ reconnectPeriod: 5000, // 断线重连间隔
|
|
|
+};
|
|
|
+
|
|
|
+let client = null;
|
|
|
+let subscribers = []; // 记录订阅的主题,重连时重新订阅
|
|
|
+
|
|
|
+const MqttPlugin = {
|
|
|
+ install(Vue, options = {}) {
|
|
|
+ const mqttClient = {
|
|
|
+ // 连接
|
|
|
+ connect() {
|
|
|
+ if (client && client.connected) {
|
|
|
+ console.log("MQTT 已连接");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ client = mqtt.connect(MQTT_URL, OPTIONS);
|
|
|
+
|
|
|
+ client.on("connect", () => {
|
|
|
+ console.log("✅ MQTT 连接成功");
|
|
|
+ Message.success("MQTT 连接成功");
|
|
|
+
|
|
|
+ // 重连后重新订阅所有主题
|
|
|
+ subscribers.forEach((topic) => {
|
|
|
+ this.subscribe(topic);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ client.on("error", (err) => {
|
|
|
+ console.error("❌ MQTT 连接错误:", err);
|
|
|
+ Message.error("MQTT 连接失败");
|
|
|
+ client.end();
|
|
|
+ });
|
|
|
+
|
|
|
+ client.on("reconnect", () => {
|
|
|
+ console.log("🔁 MQTT 正在重连...");
|
|
|
+ Message.warning("MQTT 正在重连...");
|
|
|
+ });
|
|
|
+
|
|
|
+ client.on("message", (topic, payload) => {
|
|
|
+ const data = payload.toString();
|
|
|
+ console.log("📩 收到消息:", topic, data);
|
|
|
+
|
|
|
+ // 触发全局事件(可选)
|
|
|
+ Vue.prototype.$eventBus &&
|
|
|
+ Vue.prototype.$eventBus.$emit("mqtt-message", { topic, data });
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 发布消息
|
|
|
+ publish(topic, message, options = {}) {
|
|
|
+ if (client && client.connected) {
|
|
|
+ client.publish(topic, message, options, (err) => {
|
|
|
+ if (err) {
|
|
|
+ console.error("❌ 发布失败:", err);
|
|
|
+ } else {
|
|
|
+ console.log("📤 已发布:", topic, message);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ console.warn("⚠️ MQTT 未连接,无法发布:", topic);
|
|
|
+ Message.warning("MQTT 未连接,无法发布消息");
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 订阅主题
|
|
|
+ subscribe(topic, opts, callback) {
|
|
|
+ if (client && client.connected) {
|
|
|
+ client.subscribe(topic, opts, (err) => {
|
|
|
+ if (!err) {
|
|
|
+ console.log("✅ 已订阅:", topic);
|
|
|
+ if (!subscribers.includes(topic)) {
|
|
|
+ subscribers.push(topic);
|
|
|
+ }
|
|
|
+ callback && callback();
|
|
|
+ } else {
|
|
|
+ console.error("❌ 订阅失败:", err);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ console.warn("⚠️ MQTT 未连接,无法订阅:", topic);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 取消订阅
|
|
|
+ unsubscribe(topic, callback) {
|
|
|
+ if (client && client.connected) {
|
|
|
+ client.unsubscribe(topic, (err) => {
|
|
|
+ if (!err) {
|
|
|
+ console.log("🗑️ 已取消订阅:", topic);
|
|
|
+ subscribers = subscribers.filter((t) => t !== topic);
|
|
|
+ callback && callback();
|
|
|
+ } else {
|
|
|
+ console.error("❌ 取消订阅失败:", err);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 断开连接
|
|
|
+ disconnect() {
|
|
|
+ if (client) {
|
|
|
+ client.end();
|
|
|
+ console.log("🔌 MQTT 已断开");
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取客户端状态
|
|
|
+ isConnected() {
|
|
|
+ return client && client.connected;
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ // 挂载到 Vue 原型
|
|
|
+ Vue.prototype.$mqtt = mqttClient;
|
|
|
+
|
|
|
+ // 可选:自动连接
|
|
|
+ if (options.autoConnect !== false) {
|
|
|
+ mqttClient.connect();
|
|
|
+ }
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+export default MqttPlugin;
|