需求:根据后端给的接口,前端实现消息订阅和消息加密连接操作,不走后端直接和硬件设备进行操作
mqtt会自动筛选重复的主题,也就是说订阅了某个主题之后再次添加主题后不会有重复订阅的效果
1.下载mqttx
官网链接:MQTTX: Your All-in-one MQTT Client Toolbox
根据自己电脑选择不同的操作系统,默认下载后是英文的
英文版改为中文
2.根据后端提供链接地址进行连接
高级的部分都别动,连接编辑好后点击右上角就可以连接了
添加订阅的主题名称,如果是测试的话可以随便输入,比如/test
Qos是决定消息质量,Qos:0,是发送端只发送一次,不管服务端收到没,1是至少发送一次,反正服务端一定能收到 1次,有可能收到2次以上,2保证服务端收到且只收到一次,值越大质量越高,qos越小,网络带宽越低。耗能越低
3.前端mqtt连接,并且进行加密操作
这边的加密操作,其实也就是不能让连接地址暴露在浏览器的控制台里,所以我直接把加密的连接地址进行解密的操作再做链接。其实这个方法就应该要后端把加密的连接通过接口的形式给前端,前端再进行解密,这样就安全些。
下载mqtt和crypto-js,注意!!!mqtt版本为4.3.7,最新版可能会报错找不到on
npm install mqtt crypto-js -S
加密代码
文本加密
var ciphertext = CryptoJS.AES.encrypt('连接地址', 'secret key 123').toString();
封装代码:
import mqtt from "mqtt";
import Vue from 'vue';
import CryptoJS from 'crypto-js';
var vm = new Vue();
class mqttHandle {
constructor(subscribe) {
this.connect = {
clean: true, // 保留会话
cleanSession: true,
connectTimeout: 7000, // 超时时间
reconnectPeriod: 7000, // 重连时间间隔
// 认证信息
clientId: Number(new Date()).toString(),
username: 'root3',
password: '123456'
}
this.subscription = {
topic: subscribe, //需要传入数组的包含订阅的名称
qos: 2,
}
this.mqttClient = null;
}
/**
* 创建链接
* @returns client
*/
createConnect() {
//配置链接
const { ...options } = this.connect;
const bytes = CryptoJS.AES.decrypt('加密后的内容', 'secret key 123');
const connectUrl = bytes.toString(CryptoJS.enc.Utf8);
try {
this._client = mqtt.connect(connectUrl, options);
} catch (error) {
console.log("连接失败", error);
}
this._client.on("connect", () => {
console.log("连接成功!");
});
this._client.on('reconnect', (error) => {
console.log('正在重连', error)
})
this._client.on("error", (error) => {
console.log("连接失败", error);
});
// 连接断开后触发的回调
this._client.on('close', function () {
console.log('已断开连接');
});
//配置topic
const { topic, qos } = this.subscription;
this._client.subscribe(topic, { qos: qos }, (error, res) => {
if (error) {
console.log("Subscribe to topics error", error);
return;
}
console.log("Subscribe to topics res", res);
});
this.mqttClient = this._client;
return this.mqttClient;
}
}
export default mqttHandle;
vue完整代码如下
<!--
* @Descripttion: 在Vue项目中使用mqtt
* @version:
* @Author: 叫我欧皇大人
* @email: 13071200550@163.com
* @Date: 2023-07-10
-->
<template>
<div class="content-box">
<div class="container">
<div class="chatroomBox">
{{ dataChart }}
<el-row :gutter="20">
<el-col :span="12"><el-input v-model="message" placeholder="请输入内容"></el-input></el-col>
<el-col :span="12">
<el-button @click="mqttPublish" type="success" round>发送消息</el-button>
<el-button @click="subscribe()">订阅b主题</el-button>
<el-button @click="unSubscribe()">取消订阅</el-button>
</el-col>
</el-row>
<br />
<el-row>
<el-col :span="12"> <el-button @click="createMqtt" type="success" round>开始连接</el-button></el-col>
<el-col :span="6">
<el-button @click="endConnect" type="success" round>关闭连接</el-button>
</el-col>
</el-row>
</div>
</div>
<hr />
</div>
</template>
<script>
import mqttHandle from '../../components/mqtt';
var mqtt; //mqtt 处理对象(全局变量)
var client;
var topicSends = ['aa', '/test']; //订阅的topic 例如:["Time1", "EngineMain1", "Console1", "Location1"]
export default {
data() {
return {
message: '',
dataChart: null
};
},
mounted() {},
watch: {},
methods: {
/**
* @name:初始化mqtt
* @msg:
* @param {*}
* @return {*}
*/
createMqtt() {
mqtt = new mqttHandle(topicSends);
client = mqtt.createConnect();
// client.publish('Online/+',"5265481545125")
client.on('message', (topic, message) => {
try {
console.log('message: ', JSON.parse(message.toString()));
} catch (error) {
console.log(error);
}
});
},
//关闭链接
endConnect() {
if (client != null) {
client.end(true, null, () => {
client = null;
});
}
},
mqttPublish() {
// 设备必须有这个主题,才能发布消息给他,只能发,前端收不到消息因为没有订阅主题
// let topic = 'topicSends'; //和后台约定好的主题
client.publish('/test', JSON.stringify(this.message));
},
// 订阅b主题
subscribe() {
topicSends = ['aa', '/test', 'bb'];
client.subscribe(topicSends, (err, res) => {
if (err) {
console.logh('订阅失败');
return;
}
console.log('订阅成功', res);
});
},
// 取消订阅某个主题或者全部取消订阅;
unSubscribe() {
client.unsubscribe(topicSends, function(error) {
if (error) {
console.log(error);
} else {
console.log('取消订阅成功!');
}
});
}
/**
* @name:发布mqtt消息
* @msg:
* @param {*}
* @return {*}
*/
},
beforeDestroy() {
if (client != null) {
client.end(true, null, () => {
client = null;
});
}
}
};
</script>
<style scoped lang="less">
.chatroomBox {
width: 800px;
height: 500px;
}
/deep/.el-textarea__inner {
height: 200px;
}
</style>
4.效果
文章到此结束,希望对你有所帮助,有不懂的可以在评论区或者私信我~