vue項(xiàng)目中使用mqtt通信的方法完整示例

一、 什么是 MQTT?
MQTT(Message Queuing Telemetry Transport)是一種輕量級(jí)、基于發(fā)布-訂閱模式的消息傳輸協(xié)議,適用于資源受限的設(shè)備和低帶寬、高延遲或不穩(wěn)定的網(wǎng)絡(luò)環(huán)境。它在物聯(lián)網(wǎng)應(yīng)用中廣受歡迎,能夠?qū)崿F(xiàn)傳感器、執(zhí)行器和其它設(shè)備之間的高效通信。
二、MQTT 的工作原理
MQTT 是基于發(fā)布-訂閱模式的通信協(xié)議,由 MQTT 客戶端通過(guò)主題(Topic)發(fā)布或訂閱消息,通過(guò) MQTT Broker 集中管理消息路由,并依據(jù)預(yù)設(shè)的服務(wù)質(zhì)量等級(jí)(QoS)確保端到端消息傳遞可靠性。
QoS
MQTT 提供了三種服務(wù)質(zhì)量(QoS),在不同網(wǎng)絡(luò)環(huán)境下保證消息的可靠性。
- QoS 0:消息最多傳送一次。如果當(dāng)前客戶端不可用,它將丟失這條消息。
- QoS 1:消息至少傳送一次。
- QoS 2:消息只傳送一次。
關(guān)于 MQTT QoS 的更多詳情,請(qǐng)參閱文章 MQTT QoS 0, 1, 2 介紹。
三、MQTT 的工作流程
在了解了 MQTT 的基本組件之后,讓我們來(lái)看看它的一般工作流程:
- 客戶端使用 TCP/IP 協(xié)議與 Broker 建立連接,可以選擇使用 TLS/SSL 加密來(lái)實(shí)現(xiàn)安全通信。客戶端提供認(rèn)證信息,并指定會(huì)話類型(Clean Session 或 Persistent Session)。
- 客戶端既可以向特定主題發(fā)布消息,也可以訂閱主題以接收消息。當(dāng)客戶端發(fā)布消息時(shí),它會(huì)將消息發(fā)送給 MQTT Broker;而當(dāng)客戶端訂閱消息時(shí),它會(huì)接收與訂閱主題相關(guān)的消息。
- MQTT Broker 接收發(fā)布的消息,并將這些消息轉(zhuǎn)發(fā)給訂閱了對(duì)應(yīng)主題的客戶端。它根據(jù) QoS 等級(jí)確保消息可靠傳遞,并根據(jù)會(huì)話類型為斷開(kāi)連接的客戶端存儲(chǔ)消息。
四、MQTT 基礎(chǔ)和配置
1.安裝和引入 MQTT 客戶端庫(kù)
使用 NPM 或 Yarn 來(lái)安裝 mqtt.js 是一個(gè)直接且高效的方式,這將允許你將MQTT集成到你的Vue項(xiàng)目中。安裝方式如下:
npm install mqtt --save or yarn add mqtt
在 Vue 項(xiàng)目中使用 MQTT 首先要進(jìn)行客戶端庫(kù)的安裝:
import mqtt from 'mqtt'
2.配置 MQTT 連接
連接前需要配置好MQTT服務(wù)器的地址和端口:
const options = {
host: '你的MQTT服務(wù)器地址',
port: 你的MQTT服務(wù)器端口,
username: 'admin', // 實(shí)際環(huán)境中應(yīng)使用JWT令牌
password: 'public',
clean: false, // true默認(rèn)值/false 保持會(huì)話,重連后可接收離線消息
connectTimeout: 40000, // 超時(shí)時(shí)間設(shè)置
clientId: 'emqx_vue2_' + Math.random().toString(16).substring(2, 8), // 客戶端ID
// 60秒心跳,表示客戶端將每隔60秒發(fā)送一次心跳包(PINGREQ)到服務(wù)器,服務(wù)器會(huì)響應(yīng)
keepalive: 60,
// 其他配置...
};
3.連接服務(wù)器和會(huì)話管理
連接 MQTT 服務(wù)器
創(chuàng)建 MQTT 客戶端實(shí)例并進(jìn)行連接:
const client = mqtt.connect(options);
管理 MQTT 會(huì)話
你可以通過(guò)監(jiān)聽(tīng)不同的事件來(lái)管理會(huì)話,例如:
client.on('connect', () => {
console.log('連接成功');
});
client.on('error', (err) => {
console.error('連接失敗:', err);
});
4.主題訂閱與發(fā)布消息
訂閱主題
訂閱 MQTT 主題,以便接收相關(guān)消息:
client.subscribe('你的主題', { qos: 1 }, (err) => {
if (err) {
console.error('訂閱失敗:', err);
} else {
console.log('訂閱成功');
}
});
5.發(fā)布消息
向特定主題發(fā)布消息:
client.publish('你的主題', '要發(fā)送的消息內(nèi)容', { qos: 1, retAIn: false }, (err) => {
if (err) {
console.error('發(fā)布消息失敗:', err);
}
});
6.處理收到的消息
設(shè)置消息監(jiān)聽(tīng)器
接收并處理來(lái)自訂閱主題的消息:
// 接收消息處理
client.on('message', (topic, message) => {
console.log(`收到消息:${message.toString()}`);
});
7.斷開(kāi)連接
client.on('unsubscribe', error => {
console.log('斷開(kāi)連接:', error)
})
8.安全性和性能優(yōu)化
實(shí)現(xiàn) TLS 加密連接
確保通信的安全性,可以使用 TLS 對(duì)鏈接進(jìn)行加密處理:
const options = {
//...其他配置
connectTimeout: 4000, // 超時(shí)時(shí)間設(shè)置
// 使用 TLS
ca: fs.readFileSync('path/to/ca.crt'),
key: fs.readFileSync('path/to/client.key'),
cert: fs.readFileSync('path/to/client.crt'),
rejectUnauthorized: false
};
QoS 和持久會(huì)話
設(shè)置 QoS 等級(jí)以及是否開(kāi)啟持久會(huì)話,以滿足不同的業(yè)務(wù)需求:
const options = {
...其他配置,
clean: true, // 設(shè)置為false開(kāi)啟持久會(huì)話
qos: 1 // 消息至少傳送一次
};
注:
- clean: true 干凈會(huì)話 | 每次連接都創(chuàng)建新的會(huì)話,不保留任何狀態(tài);
- clean: false 持久會(huì)話保留會(huì)話狀態(tài),包括訂閱和未送達(dá)的消息;
9.斷線重連和異常處理
處理斷線重連
監(jiān)聽(tīng) close 事件,并制定重連策略:
client.on('close', () => {
console.log('連接關(guān)閉,嘗試重連');
// 實(shí)現(xiàn)重連邏輯...
});
異常處理建議
編寫合適的異常處理邏輯來(lái)保障系統(tǒng)穩(wěn)定運(yùn)行
// 可以結(jié)合 try...catch 使用
try {
// MQTT 相關(guān)操作
} catch (error) {
console.error('異常信息:', error);
}
通過(guò)以上步驟,Vue 項(xiàng)目中就可以有效集成并使用 MQTT 通信技術(shù)了。根據(jù)不同項(xiàng)目的特點(diǎn)和需求,這些步驟可能會(huì)有所調(diào)整和優(yōu)化。
五、相關(guān)問(wèn)答
1. Vue項(xiàng)目如何使用MQTT進(jìn)行通信?
MQTT(Message Queuing Telemetry Transport)是一種輕量級(jí)的、可靠的、基于發(fā)布/訂閱模式的消息傳輸協(xié)議。在Vue項(xiàng)目中,您可以使用MQTT實(shí)現(xiàn)實(shí)時(shí)的消息傳遞和通信。
首先,您需要確保您的Vue項(xiàng)目中已經(jīng)安裝了MQTT客戶端庫(kù)。您可以使用npm或yarn來(lái)安裝依賴項(xiàng)。例如,您可以運(yùn)行以下命令來(lái)安裝一個(gè)常用的MQTT庫(kù):
npm install mqtt --save
接下來(lái),在您的Vue組件中引入MQTT庫(kù)并創(chuàng)建一個(gè)MQTT客戶端實(shí)例。您需要指定MQTT服務(wù)器的主機(jī)名和端口號(hào),并且可以選擇配置其他參數(shù),如用戶名、密碼等。例如:
import mqtt from 'mqtt'
const client = mqtt.connect('mqtt://mqtt.server.com:1883', {
username: 'your_username',
password: 'your_password'
})
一旦建立了MQTT客戶端連接,您可以使用MQTT提供的API發(fā)送和接收消息。您可以使用publish()方法發(fā)送消息,使用subscribe()方法訂閱主題,并使用on()方法監(jiān)聽(tīng)收到的消息。例如:
// 發(fā)送消息
client.publish('topic', 'Hello, MQTT!')
// 訂閱主題,并監(jiān)聽(tīng)收到的消息
client.subscribe('topic')
client.on('message', function (topic, message) {
console.log('Received message:', message.toString())
})
通過(guò)使用這些API,您可以在Vue項(xiàng)目中使用MQTT進(jìn)行實(shí)時(shí)通信,實(shí)現(xiàn)實(shí)時(shí)消息傳遞的功能。
2. 如何在Vue項(xiàng)目中配置MQTT的TLS安全連接?
如果您的MQTT服務(wù)器要求使用TLS(Transport Layer Security)安全連接,您可以在Vue項(xiàng)目中進(jìn)行相應(yīng)的配置來(lái)實(shí)現(xiàn)安全的MQTT通信。
首先,您需要獲得MQTT服務(wù)器的TLS證書文件,通常是一個(gè).pem文件。將該證書文件保存到您的Vue項(xiàng)目中的某個(gè)目錄下,例如public目錄
接下來(lái),在您的Vue組件中引入MQTT庫(kù),并使用tls選項(xiàng)指定TLS相關(guān)配置。例如:
import mqtt from 'mqtt'
import fs from 'fs'
const options = {
host: 'mqtt.server.com',
port: 8883,
key: fs.readFileSync('public/client.key'),
cert: fs.readFileSync('public/client.crt'),
ca: fs.readFileSync('public/ca.crt')
}
const client = mqtt.connect(options)
在上面的示例中,key、cert和ca選項(xiàng)分別指定了客戶端的私鑰、證書和服務(wù)器的CA證書。您需要將這些選項(xiàng)的值替換為相應(yīng)的文件路徑。
通過(guò)使用上述配置,您的Vue項(xiàng)目將能夠通過(guò)TLS安全連接與MQTT服務(wù)器進(jìn)行通信。
3. 如何實(shí)現(xiàn)Vue項(xiàng)目中的雙向MQTT通信?
雙向MQTT通信在Vue項(xiàng)目中非常有用,它允許您實(shí)時(shí)地發(fā)送和接收來(lái)自MQTT服務(wù)器的消息。
首先,您需要?jiǎng)?chuàng)建兩個(gè)獨(dú)立的MQTT客戶端實(shí)例,一個(gè)用于發(fā)送消息,一個(gè)用于接收消息。例如:
import mqtt from 'mqtt'
const sendClient = mqtt.connect('mqtt://mqtt.server.com:1883')
const receiveClient = mqtt.connect('mqtt://mqtt.server.com:1883')
接下來(lái),您可以使用sendClient發(fā)送消息,使用receiveClient接收消息。例如:
// 發(fā)送消息
sendClient.publish('topic', 'Hello, MQTT!')
// 接收消息
receiveClient.subscribe('topic')
receiveClient.on('message', function (topic, message) {
console.log('Received message:', message.toString())
})
通過(guò)使用兩個(gè)獨(dú)立的客戶端實(shí)例,您可以在Vue項(xiàng)目中實(shí)現(xiàn)雙向的MQTT通信,實(shí)時(shí)地發(fā)送和接收消息。這樣,您就可以構(gòu)建類似實(shí)時(shí)聊天、實(shí)時(shí)數(shù)據(jù)更新等功能。
4.client.on('close') 與 client.on('unsubscribe') 的區(qū)別詳解
這兩個(gè)事件監(jiān)聽(tīng)的是MQTT客戶端生命周期中完全不同階段的行為,讓我詳細(xì)解釋它們的區(qū)別:
事件對(duì)比總覽
| 事件 | 觸發(fā)時(shí)機(jī) | 用途 | 參數(shù) | 頻率 |
|---|---|---|---|---|
| close | 連接完全關(guān)閉時(shí) | 連接生命周期管理 | 無(wú) | 每個(gè)連接1次 |
| unsubscribe | 成功取消訂閱主題時(shí) | 訂閱管理 | 取消的主題數(shù)組 | 可多次觸發(fā) |
詳細(xì)解析
1. client.on('close') - 連接關(guān)閉事件
觸發(fā)時(shí)機(jī):當(dāng)MQTT客戶端與服務(wù)器的連接完全關(guān)閉時(shí)觸發(fā)。
client.on('close', () => {
console.log('?? MQTT連接已完全關(guān)閉');
// 執(zhí)行清理操作
});
典型場(chǎng)景:
const client = mqtt.connect('ws://broker.emqx.io:8083/mqtt');
// 手動(dòng)關(guān)閉連接
client.end(false, () => {
// 這里的回調(diào)執(zhí)行后會(huì)觸發(fā) 'close' 事件
});
// 監(jiān)聽(tīng)關(guān)閉事件
client.on('close', () => {
console.log('連接已關(guān)閉,可以進(jìn)行資源清理');
updateUIStatus('disconnected');
});
// 其他可能觸發(fā)close的情況:
// - 網(wǎng)絡(luò)斷開(kāi)
// - 服務(wù)器主動(dòng)關(guān)閉連接
// - 客戶端調(diào)用 client.end()
client.on('unsubscribe')- 取消訂閱事件
觸發(fā)時(shí)機(jī):當(dāng)客戶端成功從主題取消訂閱時(shí)觸發(fā)。
client.on('unsubscribe', (unsubscribedTopics) => {
console.log('? 成功取消訂閱:', unsubscribedTopics);
// unsubscribedTopics 是一個(gè)數(shù)組,包含取消的主題列表
});
典型場(chǎng)景:
// 訂閱多個(gè)主題
client.subscribe(['topic/sensors', 'topic/status', 'topic/alerts'], { qos: 1 });
// 后來(lái)取消部分訂閱
client.unsubscribe(['topic/alerts', 'topic/status'], (err) => {
if (!err) {
console.log('取消訂閱命令已發(fā)送');
}
});
// 監(jiān)聽(tīng)取消訂閱成功事件
client.on('unsubscribe', (topics) => {
console.log(`已取消訂閱: ${topics.join(', ')}`);
// 更新UI,移除對(duì)應(yīng)的主題顯示
topics.forEach(topic => removeTopicFromUI(topic));
});
總結(jié)
關(guān)鍵區(qū)別:
close:連接級(jí)別的生命周期事件,表示整個(gè)MQTT連接的終止unsubscribe:訂閱級(jí)別的操作事件,表示從特定主題取消訂閱
使用建議:
- 用
close事件處理連接斷開(kāi)后的全局清理工作 - 用
unsubscribe事件管理訂閱狀態(tài)和更新UI - 記住事件觸發(fā)的順序:取消訂閱操作 →
unsubscribe事件 → 斷開(kāi)連接 →close事件
六、項(xiàng)目實(shí)例
首先在項(xiàng)目中新建src/Utils/sysconstant.js文件用來(lái)配置常用信息
//?正式環(huán)境 export const MQTT_SERVICE = window.tsl_global_config.mqttService.url export const MQTT_USERNAME = window.tsl_global_config.mqttService.username export const MQTT_PASSWORD = window.tsl_global_config.mqttService.password
在vue2組件使用MQTT通信
import { connect as mqttConnect } from 'mqtt'
import { MQTT_SERVICE, MQTT_USERNAME, MQTT_PASSWORD } from '@/Utils/sysconstant.js'
let client = null
// 初始化MQTT連接
const options = {
connectTimeout: 40000,
clientId: 'emqx_vue3_' + Math.random().toString(16).substring(2, 8),
keepalive: 60, // 60秒心跳
username: MQTT_USERNAME,
password: MQTT_PASSWORD,
clean: false, // 保持會(huì)話,重連后可接收離線消息
}
// 連接到broker
client = mqttConnect.connect(MQTT_SERVICE, options)
mounted() {
this.getMqttMsg()
},
methods: {
getMqttMsg() {
// 連接成功
client.on('connect', () => {
// console.log('連接成功:', e)
// 彈窗提示
ElNotification(
{
title: '連接成功',
message: '已成功連接到消息服務(wù)器',
type: 'success',
duration: 3000
}
)
// 訂閱用戶專屬主題
const topics = [ `user/${this.userId}/notifications`, `user/${this.userId}/recall` ]
client.subscribe(topics, { qos: 1 }, (err) => {
if (!err) {
console.log(`已訂閱主題: ${topics.join(', ')}`)
} else {
console.error('訂閱主題失敗:', err)
Notification.error({
title: '訂閱失敗',
message: '無(wú)法訂閱通知主題'
})
}
})
// 或者分開(kāi)訂閱用戶專屬主題
client.subscribe('user/${this.userId}/notifications',{ qos: 1 },error => {
if (!error) {
// console.log('訂閱成功1')
} else {
console.log('訂閱失敗1')
ElNotification(
{
title: '訂閱失敗',
message: '無(wú)法訂閱通知主題',
type: 'error'
}
)
}
})
client.subscribe('`user/${this.userId}/recall',{ qos: 1 }, error => {
if (!error) {
// console.log('訂閱成功2')
} else {
console.log('訂閱失敗2')
}
})
})
// 接收消息處理
client.on('message', (topic, message) => {
// console.log('收到來(lái)自', topic, '的消息', message.toString())
// 處理接收的消息
if (topic === '/captureLog/platform/car') {
let carMqttObj = JSON.parse(message.toString())
carMqttObj.captureTime = formatDate(carMqttObj.captureTime, 'HH:mm')
this.carRecords.unshift(carMqttObj)
console.log(this.carRecords, 'this.carRecords')
} else {
let peopleMqttObj = JSON.parse(message.toString())
peopleMqttObj.openTime = formatDate(peopleMqttObj.openTime, 'HH:mm')
this.manRecords.unshift(peopleMqttObj)
}
})
}
// 連接斷開(kāi)
client.on('close', () => {
console.log('MQTT連接已關(guān)閉')
// this.connected = false
// this.scheduleReconnect()
})
// 連接錯(cuò)誤
client.on('error', (err) => {
this.connected = false
console.error('MQTT錯(cuò)誤:', err)
Notification.error({
title: '連接錯(cuò)誤',
message: '消息服務(wù)連接發(fā)生錯(cuò)誤'
})
this.scheduleReconnect()
})
// 重連中
client.on('reconnect', () => {
console.log('正在重連到MQTT服務(wù)器...')
})
},
總結(jié)
到此這篇關(guān)于vue項(xiàng)目中使用mqtt通信的文章就介紹到這了,更多相關(guān)vue使用mqtt通信內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue3哈希模式實(shí)現(xiàn)錨點(diǎn)導(dǎo)航方式
這篇文章主要介紹了Vue3哈希模式實(shí)現(xiàn)錨點(diǎn)導(dǎo)航方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04
vue學(xué)習(xí)筆記之給組件綁定原生事件操作示例
這篇文章主要介紹了vue學(xué)習(xí)筆記之給組件綁定原生事件操作,結(jié)合實(shí)例形式詳細(xì)分析了vue.js組件綁定原生事件相關(guān)原理、實(shí)現(xiàn)方法與操作注意事項(xiàng),需要的朋友可以參考下2020-02-02
vue3中?provide?和?inject?用法小結(jié)
父子組件傳遞數(shù)據(jù)時(shí),使用的是props和emit,父?jìng)髯訒r(shí),使用的是?props,如果是父組件傳孫組件時(shí),就需要先傳給子組件,子組件再傳給孫組件,如果多個(gè)子組件或多個(gè)孫組件使用時(shí),就需要傳很多次,會(huì)很麻煩,這篇文章主要介紹了vue3中?provide?和?inject?用法,需要的朋友可以參考下2023-11-11
element-plus的自動(dòng)導(dǎo)入和按需導(dǎo)入方式詳解
之前使用 ElementPlus 做項(xiàng)目的時(shí)候,由于不會(huì)使用按需引入耽誤了不少時(shí)間,這篇文章主要給大家介紹了關(guān)于element-plus自動(dòng)導(dǎo)入和按需導(dǎo)入的相關(guān)資料,需要的朋友可以參考下2022-08-08
使用Vue組件實(shí)現(xiàn)一個(gè)簡(jiǎn)單彈窗效果
這篇文章主要介紹了使用Vue組件實(shí)現(xiàn)一個(gè)簡(jiǎn)單彈窗效果,本文主要內(nèi)容會(huì)涉及到彈窗遮罩的實(shí)現(xiàn), slot 插槽的使用方式,props 、 $emit 傳參,具體組件代碼也傳上去了。需要的朋友可以參考下2018-04-04
Vue封裝通過(guò)API調(diào)用的組件的方法詳解
在日常業(yè)務(wù)開(kāi)發(fā)中我們會(huì)經(jīng)常封裝一些業(yè)務(wù)組件,下面這篇文章主要給大家介紹了關(guān)于Vue封裝通過(guò)API調(diào)用的組件的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-12-12
vue3使用particles插件實(shí)現(xiàn)粒子背景的方法詳解
這篇文章主要為大家詳細(xì)介紹了vue3使用particles插件實(shí)現(xiàn)粒子背景的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03
淺談vue+webpack項(xiàng)目調(diào)試方法步驟
本篇文章主要介紹了淺談vue+webpack項(xiàng)目調(diào)試方法步驟,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09

