# 使用微信小程序连接到部署

本文主要介绍在微信小程序中使用 MQTT.js 连接到 EMQX Cloud (opens new window) 部署,进行订阅、取消订阅、收发消息等功能。

# 前提条件

  1. 注册 (opens new window) 微信小程序账号,并下载 微信开发者工具 (opens new window) 由于微信小程序安全要求比较高,在与后台服务器之间的通讯必须使用 https 或 wss 协议。所以需要登录 微信公众平台 (opens new window),在左侧菜单【开发】->【开发管理】->【开发设置】->【服务器域名】中 socket 合法域名添加部署域名。

    • EMQX Cloud 专业版部署默认连接地址是 IP,需要用户自行进行域名绑定,且进行 TLS/SSL 配置(证书链必填,否则真机调试会失败)。当 TLS/SSL 的状态为 运行中 时,刷新页面,即可在部署概览页面看到连接端口中多了一个 8084 (wss),请记住这个端口号,后续编写连接代码时,我们需要用到它。
    • 微信小程序仅支持通过 WebSocket 进行即时通信,EMQX Cloud 部署的 MQTT Over WebSocket 能够完全兼容使用在微信小程序上。因此在进行 MQTT 连接时,只能使用 wss 协议(但是客户端连接代码中需要写成 wxs
    • 更多域名相关配置说明,请参阅微信官方文档:https://developers.weixin.qq.com/miniprogram/dev/framework/ability/network.html (opens new window)

    设置小程序 socket 域名

  2. 打开已经下载好了的微信开发者工具,在页面点击新建一个小程序项目,如下图所示:

    创建微信小程序项目

# 安装依赖

推荐使用 MQTT.js v4.2.1 https://unpkg.com/mqtt@4.2.1/dist/mqtt.min.js (opens new window)(针对原生的微信小程序),若调试器可以连接但真机调试仍有问题,建议尝试切换 MQTT.js 版本

原生微信小程序 MQTT.js 可用版本有 v4.2.1v4.2.0v4.1.0v2.18.8

使用 uniapp 框架搭建微信小程序 MQTT.js 可用版本有 v4.1.0v2.18.8

在项目根目录下新建 utils 文件夹,将下载好的对应版本的 mqtt.min.js 文件放入该文件夹中,在 index.js 中通过如下方式引入 mqtt

import mqtt from "../../utils/mqtt.min.js";
1

# 连接关键代码

# 建立连接

  1. 只能使用 wss 协议,但是微信小程序中需要写为 wxs
  2. 端口为 8084(EMQX Cloud 专业版部署),但实际的端口号以 EMQX Cloud 控制台对应部署的概览页面信息为准。
  3. 连接地址末尾不要忘了带上路径 /mqtt
  4. EMQX Cloud 部署需要先在部署详情页面的【认证鉴权】->【认证】中添加用户名密码,然后写入 mqttOptions
Page({
  data: {
    client: null,
    conenctBtnText: "连接",
    host: "wx.emqxcloud.cn",
    subTopic: "testtopic/miniprogram",
    pubTopic: "testtopic/miniprogram",
    pubMsg: "Hello! I am from WeChat miniprogram",
    receivedMsg: "",
    mqttOptions: {
      username: "test",
      password: "test",
      reconnectPeriod: 1000, // 1000毫秒,设置为 0 禁用自动重连,两次重新连接之间的间隔时间
      connectTimeout: 30 * 1000, // 30秒,连接超时时间
      // 更多参数请参阅 MQTT.js 官网文档:https://github.com/mqttjs/MQTT.js#mqttclientstreambuilder-options
      // 更多 EMQ 相关 MQTT 使用教程可在 EMQ 官方博客中进行搜索:https://www.emqx.com/zh/blog
    },
  },

  setValue(key, value) {
    this.setData({
      [key]: value,
    });
  },

  connect() {
    // MQTT-WebSocket 统一使用 /path 作为连接路径,连接时需指明,但在 EMQX Cloud 部署上使用的路径为 /mqtt
    // 因此不要忘了带上这个 /mqtt !!!
    // 微信小程序中需要将 wss 协议写为 wxs,且由于微信小程序出于安全限制,不支持 ws 协议
    try {
      this.setValue("conenctBtnText", "连接中...");
      const clientId = new Date().getTime();
      this.data.client = mqtt.connect(`wxs://${this.data.host}:8084/mqtt`, {
        ...this.data.mqttOptions,
        clientId,
      });

      this.data.client.on("connect", () => {
        wx.showToast({
          title: "连接成功",
        });
        this.setValue("conenctBtnText", "连接成功");

        this.data.client.on("message", (topic, payload) => {
          wx.showModal({
            content: `收到消息 - Topic: ${topic},Payload: ${payload}`,
            showCancel: false,
          });
          const currMsg = this.data.receivedMsg ? `<br/>${payload}` : payload;
          this.setValue("receivedMsg", this.data.receivedMsg.concat(currMsg));
        });

        this.data.client.on("error", (error) => {
          this.setValue("conenctBtnText", "连接");
          console.log("onError", error);
        });

        this.data.client.on("reconnect", () => {
          this.setValue("conenctBtnText", "连接");
          console.log("reconnecting...");
        });

        this.data.client.on("offline", () => {
          this.setValue("conenctBtnText", "连接");
          console.log("onOffline");
        });
        // 更多 MQTT.js 相关 API 请参阅 https://github.com/mqttjs/MQTT.js#api
      });
    } catch (error) {
      this.setValue("conenctBtnText", "连接");
      console.log("mqtt.connect error", error);
    }
  },
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

# 订阅主题

subscribe() {
  if (this.data.client) {
    this.data.client.subscribe(this.data.subTopic)
    wx.showModal({
      content: `成功订阅主题:${this.data.subTopic}`,
      showCancel: false,
    })
    return
  }
  wx.showToast({
    title: '请先点击连接',
    icon: 'error',
  })
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 取消订阅

unsubscribe() {
  if (this.data.client) {
    this.data.client.unsubscribe(this.data.subTopic)
    wx.showModal({
      content: `成功取消订阅主题:${this.data.subTopic}`,
      showCancel: false,
    })
    return
  }
  wx.showToast({
    title: '请先点击连接',
    icon: 'error',
  })
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 发布消息

publish() {
  if (this.data.client) {
    this.data.client.publish(this.data.pubTopic, this.data.pubMsg)
    return
  }
  wx.showToast({
    title: '请先点击连接',
    icon: 'error',
  })
},
1
2
3
4
5
6
7
8
9
10

# 断开连接

disconnect() {
  this.data.client.end()
  this.data.client = null
  this.setValue('conenctBtnText', '连接')
  wx.showToast({
    title: '成功断开连接'
  })
},
1
2
3
4
5
6
7
8

项目完整代码请见:https://github.com/emqx/MQTT-Client-Examples/tree/master/mqtt-client-wechat-miniprogram (opens new window)

# 测试验证

我们在小程序中简单编写了如下应用界面,该应用具备:创建连接、订阅主题、收发消息、取消订阅、断开连接等功能。

小程序概览页面

小程序进行连接并订阅主题 testtopic/miniprogram 之后,使用 MQTT 5.0 客户端工具 - MQTT X (opens new window) 作为另一个客户端订阅主题 testtopic/# 并发送一条消息到主题 testtopic/miniprogram

使用 MQTT X 发送消息

可以看到 MQTT X 可以正常接收来到来自小程序发送过来的消息,同样,使用 MQTT X 向该主题发送一条消息时,也可以看到小程序能正常接收到该消息。

app2.png

# 更多内容

综上所述,我们实现了在微信小程序项目中创建 MQTT 连接,模拟了客户端与 MQTT 服务器进行订阅、收发消息、取消订阅以及断开连接的场景。可以在 这里 (opens new window) 下载到示例的源码,同时也可以在 GitHub (opens new window) 上找到更多其他语言的 Demo 示例。

本示例只是进行了一个简单的 MQTT 连接演示,更多复杂功能还需开发者深入了解 MQTT 协议,然后进行探索研究实践。