安装mqtt
方法一:
npm install mqtt
方法二:
在 utils 文件夹下新建mqtt.js文件,复制 MQTT.js CDN 上的打包构建后的源码至该文件中
在需要使用的地方引入
import mqtt from '@/utils/mqtt'
MQTT 基础使用
(以微信小程序为例)
mqtt服务器免费网址:http://www.yoyolife.fun/iotcls/2814
mqtt调试工具:MQTTBox
//pages/index/index.js
var mqtt = require('../../utils/mqtt')
Page({
data: {
client:null,
host:'t.yoyolife.fun',
topic:'/iot/3880/lxy',//订阅和推送的主题前缀
msg:'我点击按钮测试发送一条数据',
mqttOptions:{//配置参数
//--------------------------------------------------------基本参数
clientId: lxy,
port: 端口号,
username: 用户名,
password: 密码,
connectTimeout: 4000,//两次重新连接之间的间隔
//---------------------------------------------------------可选参数
protocolVersion: 4, //MQTT连接协议版本
clean: true,
reconnectPeriod: 1000, // 1000毫秒,两次重新连接之间的间隔
resubscribe: true // 如果连接断开并重新连接,则会再次自动订阅已订阅的主题(默认true)
}
},
onLoad() {
this.connectMqtt()
},
//微信小程序使用 WebSocket 的方式连接到 MQTT 服务器,但连接的 URL 地址中请使用 wxs 协议名称
//连接mqtt服务器及初始化数据
connectMqtt() {
var that = this
//连接事件
that.data.client = mqtt.connect(`wxs://${that.data.host}/mqtt`, that.data.mqttOptions)
//开始连接
that.data.client.on('connect', (e) => {
console.log('服务器连接成功')
wx.showToast({
title:'服务器连接成功'
})
this.subscribe()
})
//信息监听事件
that.data.client.on('message',function(topic,message){
console.log(`收到-----${message.toString()}`)
})
that.data.client.on('reconnect',(error)=>{
console.log('正在重新连接',error)
})
that.data.client.on('error',(error)=>{
console.log('连接失败',error)
})
},
//订阅主题
//info:qos:0表示最多接收一次
subscribe(){
this.data.client.subscribe(this.data.topic,{qos: 0},function(err){
if (!err){
console.log('订阅成功')
wx.showToast({
title: '主题订阅成功'
})
}
})
},
//取消订阅
unsubscribe() {
this.data.client.unsubscribe(this.data.topic)
wx.showToast({
title: '取消订阅成功'
})
},
//消息发布
publish() {
this.data.client.publish(this.data.topic, this.data.msg)
},
//断开连接
disconnect() {
this.data.client.end()
wx.showToast({
title: '断开连接成功'
})
},
})
<!--pages/index/index.wxml-->
<view class="container">
<button bindtap="publish">发布消息</button>
<button bindtap="unsubscribe">取消订阅</button>
<button bindtap="disconnect">断开连接</button>
</view>
运行结果:
MQTT 封装 API
(以vue为例)
mqttClient
//utils/mqttMethod/mqtt-client
import mqtt from "@/utils/mqtt";
const mqttClient = {
connectStatus: false,
topicAction: {},
client: null,
connectFlag: true,
initMqtt(options) {
const param = {
keepalive: 5,
clientId: options.clientId,
username: options.username,
password: options.password,
clean: true,
}
if (this.client != null) {
options.fail("mqtt连接已存在");
return;
}
try {
this.client = mqtt.connect(`MQTT服务器地址`, param);
} catch (err) {
console.log("mqtt-error", err);
this.connectFlag = false;
}
this.client.on("connect", (e) => {
options.success("mqtt连接成功");
this.connectStatus = true;
});
this.client.on("reconnect", (e) => {
options.reconnect("mqtt尝试重新连接");
this.connectStatus = true;
});
this.client.on("error", (e) => {
options.fail("mqtt连接失败");
this.connectStatus = false;
});
this.client.on("offline", (e) => {
this.connectStatus = false;
});
this.client.on("disconnect", (e) => {
this.connectStatus = false;
});
this.client.on("close", (e) => {
this.connectStatus = false;
});
this.client.on("message", (topic, message) => {
console.log(
`订阅的主题${topic}来消息了,收到message${message.toString()}`
);
//自定义处理接收到的消息
});
},
subscribe(topic, successCallback, failCallback) {
if (this.connectStatus) {
this.client.subscribe(topic, {
qos: 0
}, (err) => {
if (err) {
console.log(`订阅主题${topic}失败`);
this.topicAction[topic] = failCallback;
} else {
console.log(`订阅主题${topic}成功`);
this.topicAction[topic] = successCallback;
}
});
} else {
console.log("请先连接mqtt再订阅");
}
},
// 取消订阅
unsubscribe(topic) {
if (this.connectStatus) {
this.client.unsubscribe(topic, (err) => {
if (err) {
console.log(`取消订阅失败${err}`);
} else {
delete this.topicAction[topic];
console.log(`取消订阅成功${topic}`);
}
});
} else {
console.log("请先连接mqtt再订阅");
}
},
// 发布
publish(topic, params) {
if (this.connectStatus) {
try {
this.client.publish(
topic,
params, {
qos: 0
},
(err) => {
if (err) {
console.log(`发布主题${topic}失败`);
} else {
console.log(
`发布主题${topic}成功,参数为${params}}`
);
}
}
);
} catch (error) {
console.log(error);
}
} else {
console.log("请先连接mqtt再订阅");
}
},
mqttToReturn({
getTopic,
putTopic,
params,
success,
fail
}) {
if (getTopic != null && putTopic != null) {
this.subscribe(getTopic, success, fail);
this.publish(putTopic, params);
} else if (getTopic != null && putTopic == null) {
this.subscribe(getTopic, success, fail);
} else if (putTopic == null && putTopic != null) {
this.publish(putTopic, params);
}
},
closeMqtt(callback) {
this.client.end();
this.client = null;
callback && callback();
},
cleanTopic() {
Object.keys(this.topicAction).forEach((e) => {
if (!e.includes("property")) this.unsubscribe(e);
});
console.log("清除topic结束");
},
cleanAllTopic() {
Object.keys(this.topicAction).forEach((e) => {
this.unsubscribe(e);
});
console.log("清除所有topic结束");
},
cleanOneTopic(topic) {
Object.keys(this.topicAction).forEach((e) => {
if (!e.includes(topic)) this.unsubscribe(e);
});
},
};
export default mqttClient;
mqttMethod
//utils/mqttMethod/index
import _mqtt from "../mqttMethod/mqtt-client";
import mqttApi from "./mqttApi";
import api from "../httpMethod/index";
const mqttMethod = {
init(options) {
_mqtt.initMqtt(options);
},
Func1({
number,
success,
fail
}) {
mqttApi.Func1(
number,
(res) => {
success(res);
},
(error) => {
fail(error);
}
);
},
//向云端发送指令
Func2({
number,
params,
success,
fail
}) {
// 后台接口请求
api
.接口方法({
number // 参数
})
.then((res) => {
if (res.success) {
mqttApi.Func2(
number,
params,
(res) => {
success(res);
},
(error) => {
fail(error);
}
);
} else {
// 失败处理
}
});
},
// 心跳开始
keepAliveStartMethod({
params,
success,
fail
}) {
mqttApi.keepAliveStart(
params,
(res) => {
success(res);
},
(error) => {
fail(error);
}
);
},
// 心跳结束
keepAliveEndMethod({
params,
success,
fail
}) {
mqttApi.keepAliveEnd(
params,
(res) => {
success(res);
},
(error) => {
fail(error);
}
);
},
// 清除属性上报外的已订阅主题
cleanTopic() {
_mqtt.cleanTopic();
},
// 清除所有已订阅主题
cleanAllTopic() {
_mqtt.cleanAllTopic();
},
// 断开MQTT
disconnect() {
_mqtt.closeMqtt();
},
};
export default mqttMethod;
mqttApi
//utils/mqttMethod/mqttApi
import _mqtt from "./mqtt-client";
const mqttApi = {
Func1(number, success, fail) {
if (number)
_mqtt.mqttToReturn({
getTopic: `接口地址${number}`,
success,
fail,
});
},
Func2(number, params, success, fail) {
if (number)
_mqtt.mqttToReturn({
putTopic: `接口地址${number}`,
getTopic: `接口地址${number}`,
params,
success,
fail,
});
},
// 心跳开始
keepAliveStart(params, success, fail) {
_mqtt.mqttToReturn({
putTopic: `接口地址`,
params,
success,
fail,
});
},
// 心跳结束
keepAliveEnd(params, success, fail) {
_mqtt.mqttToReturn({
putTopic: `接口地址`,
params,
success,
fail,
});
},
}
export default mqttApi;
main.js
//main.js
import { methodInit } from '@/utils/device.js'
methodInit()
methodInit
//@/utils/device.js
import { useMethodStore } from '@/store/method'
import mqttMethod from '@/utils/mqttMethod/index'
export const methodInit = () => {
const methodStore = useMethodStore()
methodStore.setMethod(mqttMethod)
methodStore.method.init({
username: `用户名`,
password: `密码`,
clientId: `客户机id`,
success: (res) => {
console.log('res', res)
},
fail: (error) => {
console.log('error', error)
},
reconnect: (res) => {
console.log(res);
}
})
}
useMethodStore
//@/store/method
import { defineStore } from "pinia";
export const useMethodStore = defineStore("method", {
state: () => {
return {
method: null,
};
},
actions: {
setMethod(res) {
this.method = res;
},
},
});
Func2的使用页
<template>
<div>
<button @click="event"></button>
</div>
</template>
<script>
import { defineComponent } from 'vue'
import { useMethodStore } from '@/store/method'
export default defineComponent({
components: {},
props: {},
setup(){
const methodStore = useMethodStore()
const event = () => {
let number=0
let params={}
methodStore.method.Func2({
number,
params,
success(res) {
//mqtt接口请求成功
console.log(res)
//接口返回数据处理
},
fail() {
//mqtt接口请求失败
}
})
}
return {
event
}
}
});
</script>
<style lang="less" scoped>
</style>
知识点补充
MQTT的认识使用及SDK应用详解 - 飞书云文档 (feishu.cn)