🐟🐟🐟【微信小程序—MQTT】 一文总结 | 设备与之间通信中间件 —— MQTT

1,490 阅读3分钟

前言

先了解一下MQTT(消息队列遥测传输) 是基于发布/订阅模式的消息协议。它工作也是基于TCP协议上,为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布/订阅型消息协议。

公司最近研发一件新产品智能睡眠灯,研发阶段一直使用的是前后端交互,通过接口实现对产品功能的一系列操作。直到有一天发现切换睡眠灯的灯光模式和调节一些灯光基本参数的时候无法达到预期。

比如用户手动控制夜灯的开关灯 灯光效果 常量模式。需要设备来告诉小程序端做出相应的同步。打个比方如果我想获取或更改睡眠灯的参数信息,只限于我主动去获取或改变睡眠灯的参数。睡眠灯掉线或关灯时,我们需要知道设备希望小程序如何改变。这个场景如果使用对页面轮询获取就会显得非常不完美,这不完全出于能否实现的问题,还需要考虑公司的服务器维护产品的成本,流量,带宽,并发等。轮询原本就是一个非常消耗性能的操作,尤其是等产品开始销售后,成本、性能、体验等将是个非常糟糕的结局。

话不多说,进入MQTT接入微信小程序端的使用方案 首先需要引入MQTT

1、引入MQTT

git地址: github.com/mqttjs/MQTT…

4.1.0js文件下载地址 pan.baidu.com/s/1_PxO9znY…
提取码:g63l

2、项目中启动MQTT

//App.vue
import mqtt from "@/utils/mqtt.js";
import config from "./config.js";
export default {
  data() {
    return {
      appIsUseTimer: null,
      mqttData: {
        client: null,
        options: {
          keepalive: 30,
          reschedulePings: true,
          protocolId: "MQTT",
          protocolVersion: 4,
          reconnectPeriod: 1000,
          clean: true,
          resubscribe: true,
          connectTimeout: 30000,
          clientId: this.$store.state.userInfo.userId + new Date().getTime(), //这个地方最好用一个随机字符串方法生成
          cleanSession: true,
          username: this.$store.state.userInfo.phoneNumber,
          password: this.$store.state.userInfo.phoneNumber,
          automaticReconnect: true,
        },
      },
    };
  },
  methods: {
    connectmqtt() {
      var that = this;
      //此处需要用wxs,请注意!!!
      console.log("mqttUrl: ", config.uni_app_mqtt_url);
      that.mqttData.client = mqtt.connect(
        config.uni_app_mqtt_url,
        that.mqttData.options
      );
      that.mqttData.client.on("connect", (e) => {
        console.log("服务器连接成功", e);
      });
      that.mqttData.client.on("reconnect", (error) => {
        console.log("正在重连", error);
      });
      that.mqttData.client.on("error", (error) => {
        console.log("连接失败", error);
      });
      // 连接断开后触发的回调
      that.mqttData.client.on("close", function () {
        console.log("已断开连接");
      });
      // 客户端脱机下线触发回调
      that.mqttData.client.on("offline", function () {
        console.log("您已断开连接,请检查网络");
      });
      //当客户端发送任何数据包时发出。这包括publish()以及MQTT用于管理订阅和连接的包
      that.mqttData.client.on("packetsend", (packet) => {
        //console.log("客户端已发出报文", packet);
      });
    },
    //断开mqtt
    unconnectmqtt() {
      if (!this.mqttData.client || !this.mqttData.client.connected) {
        // this.showToast('客户端未连接', 1000)
        return;
      }
      this.mqttData.client.end();
      this.mqttData.client = null;
      // this.showToast('成功断开连接', 1000, 'success')
      console.log("断开连接");
    },
  },
  //
  onLaunch: function () {
    this.connectmqtt();
    console.log("mqtt: ", mqtt);
  },
  onUnload() {
    this.unconnectmqtt();
  },
};

OK这样启动小程序的时候就自动连接上了MQTT,mqttData.options为MQTT的一些参数配置。通过MQTT的client,可以监听到许多MQTT的状态并打印。代码中已体现此处就不过多赘述。关于一些MQTT的参数配置需要和后端沟通好即可。

3、连接MQTT的成功回调

这样就成功连接上了MQTT了。网络不佳时MQTT可能会出现断开现象,但无需多虑,MQTT会自己重连,我们只需要保证网络不出现问题。

image.png

4、订阅Topic和接受消息

image.png 项目中组件通过getApp().$vm.mqttData.client就可以获取到MQTT的client实例了。获取到client后需要订阅topic用于接受设备消息。

image.png

关注控制台你的订阅成功后的回调。打印了成功即订阅topic成功。

5、处理返回的消息

收到返回的消息需要与后端或者嵌入式沟通返回消息的含义 image.png 此处为嵌入式提供的MQTT交互命令列表。上面清楚记录了每条指令和字段含义

OK我们用灯光试一下效果

image.png

当前灯光亮度为60% 然后我们设置为100 image.png

可以看到MQTT收到订阅的消息其指令ID为2303也就是操作灯光时返回的消息 image.png

例如设备上报的温度湿度以及环境亮度,只要发生变化就可以订阅到当前主题返回的消息。无需轮询获取环境数据。 image.png

6、注意事项

  1. 使用MQTT需要做到一个账号在3端登录不会出现MQTT的client相同的情况。也就是每个端的clientId必须是唯一的且不相同。
  2. 我的处理方法是clientId: this.$store.state.userInfo.userId + new Date().getTime()。也就是使用userID + 当前毫秒的时间戳。确保clientID唯一且不相同。若默认使用用户的userID为clientID,会导致同一个账号在手机端和PC端同时登录,但是他们的clientID相同,这样会出现两边的MQTT互挤,并且无限重连的情况导致MQTT失效的情况
  3. 你的代码中要连接的mqtt的域名为wxs:/你的域名/mqtt wxs为mqtt的网络协议(请与后端人员沟通)
  4. 微信小程序需要在公众平台设置你的socket合法域名地址,协议为wss。这里我设置了两个一个为测试环境地址一个为正式环境地址
  5. 从性能和数据同步角度考虑,建议进入小程序就一直连着MQTT,组件需要用到订阅消息在当前组件订阅topic即可

image.png