在web端做一个类似MQTTX客户端工具(主要是用MQTT协议传输做设备调试)。
依赖库
vite@2.9.9
vue@2.6.11
mqtt@4.1.0
引入MQTT库
在使用到mqtt文件里引入mqtt库:
import * as mqtt from "mqtt/dist/mqtt.min";
mqtt官方介绍引入:
const mqtt = require('mqtt')import * as mqtt from "mqtt"import { connect } from "mqtt"单独引入connect方法,没试过
为什么我没有按照官网推荐的引入方式?
方式1是因为我用的vite构建工具,默认是不支持require的,然后用方式2引入,先报错:vue.esm.js:5105 [Vue warn]: Failed to resolve async component: () => import('/src/views/deviceDebug/mqtt/index.vue') Reason: ReferenceError: process is not defined,当我在vite.config.js里定义了process,又报错:[Vue warn]: Failed to resolve async component: () => import('/src/views/deviceDebug/mqtt/index.vue') Reason: TypeError: Cannot read properties of undefined (reading 'slice')
最后各种搜索,终于找到按照最上面的引入方式,才成功引入。
由于整理这篇文档和当初实现功能已经相隔甚远,所以是在哪篇文章或者github上哪个issue找到解决方案的,忘记了,等找到了再补充上去。
建立连接
mqtt集成类似websocket
let connectUrl = `ws://${this.mqttDomain}${this.mqttPath}`; // this.mqttDomain是通过后端接口返回的
// https chrome浏览器,安全机制无法直连,需要走nginx代理,所以配置当前域名,在nginx代理到实际的服务上
// 火狐浏览器是可以直连的
if (window.location.protocol === "https:") {
connectUrl = `wss://${window.location.host}${this.mqttPath}`;
}
const options = {
protocolId: "MQTT",
protocolVersion: 4,
clean: true, // 是否保留会话,如果设置false的话,离线可以收到Qos=1和=2的消息
reconnectPeriod: 0, // 毫秒,重连时间间隔, 0是不重连
connectTimeout: 4000, // 毫秒,收到CONNACK之前等待时间
// 认证信息
clientId: "",
username: "",
password: ""
}
this.client = mqtt.connect(connectUrl, options);
options还有很多设置,可参考mqtt的官方文档
注:如果连不上,可能因为后端的服务不是websocket,需要暴露websocket服务,浏览器才可以发起连接
断开连接
disconnect() {
if (this.client && this.client.end) {
this.client.end();
}
}
订阅信息
连接信息
this.client.on("connect", () => {
// 连接成功
this.connected = true;
});
消息
this.client.on("message", (topic, message) => {
console.log(topic, message.toString())
});
错误信息
this.client.on("error", error => {
console.log("error", error);
this.disconnect()
});
连接关闭
this.client.on("close", () => {
this.connected = false;
});
从服务端收到断开连接通知
this.client.on("disconnect", error => {
console.log("disconnect", error);
this.disconnect();
});
发布消息
const topic = "v1/devices/me/rpc/request/1"
const params = {
"method": "getCurrentTime",
"params": {}
}
const qos = 0
this.client.publish(topic, JSON.stringify(params), { qos }, error => {
if (!error) {
// TODO 发布成功
} else {
// TODO 发布失败
}
});
QOS:
- 0:发送就不管了,最多一次;
- 1:发送之后依赖MQTT规范,是否启动重传消息,所以至少一次;
- 2:发送之后依赖MQTT消息机制,确保只有一次。
至此web端实现mqtt协议设备调试功能基本实现了
如何使用mqtt协议发送protobuf数据
后续会继续整理,主要是利用proto schema做发送校验,转换成buffer,接收消息再读取buffer格式的消息,通过proto schema转换成json 文档:juejin.cn/post/718696…