VUE3

本文主要介绍如何在 VUE3 项目中使用 MQTT.js 客户端库 ,实现 SX-IOT设备与 MQTT 服务器的连接、订阅、收发消息等功能。

前提条件

安装依赖包

1sudo apt install nodejs npm -y
2npm install

连接使用

连接设置

本文将使用自定义的接入认证方式,服务器接入信息如下:

  • Broker: mqtt.geek-smart.cn

  • TCP Port: 1883

  • WebSocket Port: 8083

导入依赖包

1import * as mqtt from "mqtt/dist/mqtt.min";
2import { reactive, ref } from "vue";

定义连接地址、认证信息以及消息发布主题

 1 const connection = reactive({
 2   // ws or wss
 3   protocol: "ws",
 4   host: "mqtt.geek-smart.cn",
 5   // ws -> 8083; wss -> 8084
 6   port: 8083,
 7   clientId: "vue3-client",
 8
 9   username: "xxxxxxxxxxxxxx",
10   password: "xxxxxxxxxxxxxxxxxxxxxx",
11   clean: true,
12   connectTimeout: 30 * 1000, // ms
13   reconnectPeriod: 4000, // ms
14 });
15 const pub_topic = '/HYUGHV/lVtAcHuorxxx/4cebd60bfxxx/publish'
16 const sub_topic = '/HYUGHV/lVtAcHuorxxx/4cebd60bfxxx/subscribe'

定义消息发布函数

1 const publish = ref({
2   topic: pub_topic,
3   qos: 0 as mqtt.QoS,
4   payload: '{ "type": "info" }',
5 });

定义 doSubscribe,doUnSubscribe 回调函数,用于打印订阅主题接收的消息内容

 1 // subscribe topic
 2 // https://github.com/mqttjs/MQTT.js#mqttclientsubscribetopictopic-arraytopic-object-options-callback
 3 const doSubscribe = () => {
 4   btnLoadingType.value = "subscribe";
 5   const { topic, qos } = subscription.value;
 6   client.value.subscribe(
 7     topic,
 8     { qos },
 9     (error: Error, granted: mqtt.ISubscriptionGrant[]) => {
10       btnLoadingType.value = "";
11       if (error) {
12         console.log("subscribe error:", error);
13         return;
14       }
15       subscribedSuccess.value = true;
16       console.log("subscribe successfully:", granted);
17     }
18   );
19 };
20
21 // unsubscribe topic
22 // https://github.com/mqttjs/MQTT.js#mqttclientunsubscribetopictopic-array-options-callback
23 const doUnSubscribe = () => {
24   btnLoadingType.value = "unsubscribe";
25   const { topic, qos } = subscription.value;
26   client.value.unsubscribe(topic, { qos }, (error) => {
27     btnLoadingType.value = "";
28     subscribedSuccess.value = false;
29     if (error) {
30       console.log("unsubscribe error:", error);
31       return;
32     }
33     console.log(`unsubscribed topic: ${topic}`);
34   });
35 };

连接 MQTT

 1 const createConnection = () => {
 2   try {
 3     btnLoadingType.value = "connect";
 4     const { protocol, host, port, ...options } = connection;
 5     const connectUrl = `${protocol}://${host}:${port}/mqtt`;
 6
 7     client.value = mqtt.connect(connectUrl, options);
 8
 9     if (client.value.on) {
10       // https://github.com/mqttjs/MQTT.js#event-connect
11       client.value.on("connect", () => {
12         btnLoadingType.value = "";
13         console.log("connection successful");
14       });
15
16       // https://github.com/mqttjs/MQTT.js#event-reconnect
17       client.value.on("reconnect", handleOnReConnect);
18
19       // https://github.com/mqttjs/MQTT.js#event-error
20       client.value.on("error", (error) => {
21         console.log("connection error:", error);
22       });
23
24       // https://github.com/mqttjs/MQTT.js#event-message
25       client.value.on("message", (topic: string, message) => {
26         receivedMessages.value = receivedMessages.value.concat(
27           message.toString()
28         );
29         console.log(`received message: ${message} from topic: ${topic}`);
30       });
31     }
32   } catch (error) {
33     btnLoadingType.value = "";
34     console.log("mqtt.connect error:", error);
35   }
36 };

完整代码

  1 // vue 3 + vite use MQTT.js refer to https://github.com/mqttjs/MQTT.js/issues/1269
  2 import * as mqtt from "mqtt/dist/mqtt.min";
  3 import { reactive, ref } from "vue";
  4
  5 // https://github.com/mqttjs/MQTT.js#qos
  6 const qosList = [0, 1, 2];
  7
  8
  9 const connection = reactive({
 10   // ws or wss
 11   protocol: "ws",
 12   host: "mqtt.geek-smart.cn",
 13   // ws -> 8083; wss -> 8084
 14   port: 8083,
 15   clientId: "vue3-client",
 16
 17   username: "xxxxxxxxxxxxxx",
 18   password: "xxxxxxxxxxxxxxxxxxxxxx",
 19   clean: true,
 20   connectTimeout: 30 * 1000, // ms
 21   reconnectPeriod: 4000, // ms
 22 });
 23 const pub_topic = '/HYUGHV/lVtAcHuorxxx/4cebd60bfxxx/publish'
 24 const sub_topic = '/HYUGHV/lVtAcHuorxxx/4cebd60bfxxx/subscribe'
 25 // topic & QoS for MQTT subscribing
 26 const subscription = ref({
 27   topic: sub_topic,
 28   qos: 0 as mqtt.QoS,
 29 });
 30
 31 // topic, QoS & payload for publishing message
 32 const publish = ref({
 33   topic: pub_topic,
 34   qos: 0 as mqtt.QoS,
 35   payload: '{ "type": "info" }',
 36 });
 37
 38 let client = ref({
 39   connected: false,
 40 } as mqtt.MqttClient);
 41 const receivedMessages = ref("");
 42 const subscribedSuccess = ref(false);
 43 const btnLoadingType = ref("");
 44 const retryTimes = ref(0);
 45
 46 const initData = () => {
 47   client.value = {
 48     connected: false,
 49   } as mqtt.MqttClient;
 50   retryTimes.value = 0;
 51   btnLoadingType.value = "";
 52   subscribedSuccess.value = false;
 53 };
 54
 55 const handleOnReConnect = () => {
 56   retryTimes.value += 1;
 57   if (retryTimes.value > 5) {
 58     try {
 59       client.value.end();
 60       initData();
 61       console.log("connection maxReconnectTimes limit, stop retry");
 62     } catch (error) {
 63       console.log("handleOnReConnect catch error:", error);
 64     }
 65   }
 66 };
 67
 68 // create MQTT connection
 69 const createConnection = () => {
 70   try {
 71     btnLoadingType.value = "connect";
 72     const { protocol, host, port, ...options } = connection;
 73     const connectUrl = `${protocol}://${host}:${port}/mqtt`;
 74
 75     client.value = mqtt.connect(connectUrl, options);
 76
 77     if (client.value.on) {
 78       // https://github.com/mqttjs/MQTT.js#event-connect
 79       client.value.on("connect", () => {
 80         btnLoadingType.value = "";
 81         console.log("connection successful");
 82       });
 83
 84       // https://github.com/mqttjs/MQTT.js#event-reconnect
 85       client.value.on("reconnect", handleOnReConnect);
 86
 87       // https://github.com/mqttjs/MQTT.js#event-error
 88       client.value.on("error", (error) => {
 89         console.log("connection error:", error);
 90       });
 91
 92       // https://github.com/mqttjs/MQTT.js#event-message
 93       client.value.on("message", (topic: string, message) => {
 94         receivedMessages.value = receivedMessages.value.concat(
 95           message.toString()
 96         );
 97         console.log(`received message: ${message} from topic: ${topic}`);
 98       });
 99     }
100   } catch (error) {
101     btnLoadingType.value = "";
102     console.log("mqtt.connect error:", error);
103   }
104 };
105
106 const doSubscribe = () => {
107   btnLoadingType.value = "subscribe";
108   const { topic, qos } = subscription.value;
109   client.value.subscribe(
110     topic,
111     { qos },
112     (error: Error, granted: mqtt.ISubscriptionGrant[]) => {
113       btnLoadingType.value = "";
114       if (error) {
115         console.log("subscribe error:", error);
116         return;
117       }
118       subscribedSuccess.value = true;
119       console.log("subscribe successfully:", granted);
120     }
121   );
122 };
123
124 const doUnSubscribe = () => {
125   btnLoadingType.value = "unsubscribe";
126   const { topic, qos } = subscription.value;
127   client.value.unsubscribe(topic, { qos }, (error) => {
128     btnLoadingType.value = "";
129     subscribedSuccess.value = false;
130     if (error) {
131       console.log("unsubscribe error:", error);
132       return;
133     }
134     console.log(`unsubscribed topic: ${topic}`);
135   });
136 };
137
138
139 const doPublish = () => {
140   btnLoadingType.value = "publish";
141   const { topic, qos, payload } = publish.value;
142   client.value.publish(topic, payload, { qos }, (error) => {
143     btnLoadingType.value = "";
144     if (error) {
145       console.log("publish error:", error);
146       return;
147     }
148     console.log(`published message: ${payload}`);
149   });
150 };
151
152 const destroyConnection = () => {
153   if (client.value.connected) {
154     btnLoadingType.value = "disconnect";
155     try {
156       client.value.end(false, () => {
157         initData();
158         console.log("disconnected successfully");
159       });
160     } catch (error) {
161       btnLoadingType.value = "";
162       console.log("disconnect error:", error);
163     }
164   }
165 };
166
167 const handleProtocolChange = (value: string) => {
168   connection.port = value === "wss" ? 8084 : 8083;
169 };

测试验证

运行

1npm run dev