MQTT 封装

829 阅读1分钟
import * as mqtt from 'mqtt/dist/mqtt.min.js'
import { WSS_URL } from '@/constant'

function falseFn() {
  return false
}

export default class MQTT {
  constructor() {
    this.connected = false
    this.instance = null
    this.routers = {}
  }

  static getInstance() {
    if (!this.instance) {
      // console.log('创建 MQTT')
      this.instance = new MQTT()
    }
    return this.instance
  }

  connect() {
    return new Promise((resolve, reject) => {
      this.client = mqtt.connect(WSS_URL, {
        clean: true,
        clientId: 'mqtt-test' + Math.random(),
        connectTimeout: 30 * 1000,
        keepalive: 60,
        protocolVersion: 5,
        reconnectPeriod: 2000,
        reschedulePings: true,
        resubscribe: true,
      })
      this.client.on('connect', () => {
        this.connected = true
        this.client.on('message', (t, m) => {
          if (this.routers[t]) {
            for (let i = 0; i < this.routers[t].length; i++) {
              this.routers[t][i](m)
            }
          }
        })
        console.log('连接成功')
        resolve(this)
      })
      this.client.on('error', err => {
        console.log('连接失败')
        reject(err)
      })
    })
  }

  subscribe(topic, config = {}) {
    if (this.connected) {
      this.client.subscribe(topic, config, () => {
        console.log(`订阅成功:${topic}`)
      })
    }
    return this
  }

  unsubscribe(topic, config = {}) {
    this.client.unsubscribe(topic, config, () => {
      console.log(`取消订阅:${topic}`)
    })
  }

  publish(topic, message) {
    console.log(`发布消息:${topic} -> `)
    console.log(message)
    this.client.publish(topic, message, { qos: 1 })
  }

  handle(callback) {
    if (!this.client._events.message) {
      this.client.on('message', callback)
    }
  }

  addRouter(topic, callback) {
    if (!this.routers[topic]) {
      this.routers[topic] = []
    }
    this.routers[topic].push(callback)
    return callback
  }

  addRouterViaJSON(topic, callback) {
    if (!this.routers[topic]) {
      this.routers[topic] = []
    }
    const func = msg => {
      try {
        const obj = JSON.parse(msg.toString())
        callback(obj)
      } catch (e) {
        callback(null)
      }
    }
    this.routers[topic].push(func)
    return func
  }

  delRouter(topic, fn) {
    if (!this.routers[topic]) {
      return
    }
    if (fn) {
      for (let i = 0; i < this.routers[topic].length; i++) {
        if (this.routers[topic][i] === fn) {
          this.routers[topic][i] = falseFn
        }
      }
    } else {
      delete this.routers[topic]
    }
  }

  end() {
    console.log('关闭连接成功')
    this.client.end()
  }
}