WEB端实现MQTT协议设备调试功能

456 阅读2分钟

在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官方介绍引入:

  1. const mqtt = require('mqtt')
  2. import * as mqtt from "mqtt"
  3. 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找到解决方案的,忘记了,等找到了再补充上去。 image.png image.png

建立连接

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…