mqtt.js 客户端封装

mqtt.js 客户端封装

没封装前使用

const client = mqtt.connect('ws://broker.emqx.io:8083/mqtt')
onMounted(() => {
  const topicList = []
  const channelCount = 12
  for(let i = 0; i < channelCount; i++) {
    topicList.push(`/test/sendImage${i + 1}`)
  }

  client.on('connect', () => {
    console.log('connected')
    topicList.forEach((topic) => {
      client.subscribe(topic)
    })
    client.on('message', (topic, message) => {
      // 主要差别在这里,需要判断 topic 是当前订阅的,才进行处理,
      // 每次需要遍历所有的 topic 
      topicList.forEach((t, index) => {
        if(topic === t) {
          handleImage(message, index)
        }
      })
    })
  })
  client.on('error', (error) => {
    console.error('mqtt connect error', error)
  })
})
onUnmounted(() => {
  client.end()
})

封装后使用

const client = new Mqtt()
client.connect('ws://broker.emqx.io:8083/mqtt')

onMounted(() => {
  const topicList = []
  const channelCount = 12
  for(let i = 0; i < channelCount; i++) {
    topicList.push(`/test/sendImage${i + 1}`)
  }
  topicList.forEach((topic, index) => {
    // 订阅topic时,注册 callback,
    // 当前topic接收到的数据在 callback 中处理
    client.subscribe(topic, (message) => {
      handleImage(message, index)
    })
  })
})
onUnmounted(() => {
  client.disconnect()
})

封装 Mqtt class

原理是 subscribe 时,注册当前topic处理的 callback,在callback中处理接收到的数据

import mqtt, { IClientOptions, MqttClient } from 'mqtt';

export class Mqtt {
  private client: MqttClient | null = null;
  /**
   * 连接到 MQTT 服务器
   * @param brokerUrl
   * string: MQTT 服务器地址,
   * IClientOptions: 客户端配置
   * @param opts
   * @returns
   */
  connect(brokerUrl: string): MqttClient
  connect(opts: IClientOptions): MqttClient
  connect(brokerUrl: string, opts?: IClientOptions): MqttClient
  connect(
    brokerUrl: string | IClientOptions,
    opts?: IClientOptions,
  ): MqttClient {
    if(this.client) {
      console.warn('MQTT client is already connected.');
      return this.client;
    }
    // 如果第一个参数是 IClientOptions 类型,则将其赋值给 opts
    if(typeof brokerUrl === 'object') {
      opts = brokerUrl;
      brokerUrl = ''; // 如果 brokerUrl 是空字符串,mqtt.connect 会使用 opts 中的 brokerUrl
    }

    // 确保 opts 不为空
    opts = opts || {};

    // 调用 mqtt.connect
    this.client = mqtt.connect(brokerUrl, opts);
    this.client.on('connect', () => {
      console.log('Connected to MQTT broker');
    })
    this.client.on('error', (error) => {
      console.error('MQTT error:', error);
    });

    this.client.on('close', () => {
      console.log('Disconnected from MQTT broker');
    });
    return this.client;
  }

  /**
  * 订阅主题
  * @param topic 主题
  * @param callback 消息回调函数
  */
  subscribe(topic: string, callback: (message: any) => void): void {
    if(!this.client) {
      console.error('MQTT client is not connected.');
      return;
    }
    this.client.subscribe(topic, (err) => {
      if(err) {
        console.error('Subscription error:', err);
      } else {
        console.log(`Subscribed to topic: ${topic}`);
      }
    });
    this.client.on('message', (receivedTopic, message) => {
      if(receivedTopic === topic) {
        callback(message);
      }
    })
  }

  unsubscribe(topic: string, callback?: (packet?: mqtt.Packet) => void) {
    if(!this.client) {
      console.error('MQTT client is not connected.');
      return;
    }
    this.client.unsubscribe(topic, (err, packet?) => {
      if(err) {
        console.error('Unsubscription error:', err);
      } else {
        console.log(`Unsubscribed from topic: ${topic}`);
        callback?.(packet)
      }
    });
  }

  /**
  * 发布消息到主题
  * @param topic 主题
  * @param message 消息内容
  */
  publish(topic: string, message: any, callback?: (packet?: mqtt.Packet) => void) {
    if(!this.client) {
      console.error('MQTT client is not connected.');
      return;
    }
    this.client.publish(topic, message, (err, packet) => {
      if(err) {
        console.error('Publish error:', err);
      } else {
        console.log(`Message published to topic: ${topic}`);
        callback?.(packet)
      }
    })
  }

  /**
   * 断开连接
   */
  disconnect() {
    if(this.client) {
      this.client.end();
      this.client = null;
    }
  }
}

结语:

以上是对 mqtt.js 的简单业务封装。当然还有其他的封装方式,只需要满足当前的业务需求即可。

### uniapp 中集成和使用 MQTT.js 的实现方法 在 UniApp 开发环境中,可以借助 `MQTT.js` 来完成消息的订阅与发布功能。以下是具体实现方式: #### 1. 安装依赖库 首先,在项目根目录下通过 npm 或 yarn 安装 `mqtt` 库: ```bash npm install mqtt --save ``` 安装完成后,确保该模块已正确引入到项目的构建流程中。 --- #### 2. 封装 MQTT 工具类 为了便于管理 MQTT 连接状态以及简化操作逻辑,建议创建一个独立的工具文件来封装 MQTT 功能。例如,在 `/utils/sendMqtt.js` 文件中定义如下内容: ```javascript import mqtt from 'mqtt'; let client = null; // 创建 MQTT 客户端实例并连接服务器 function createMqtt(options) { const url = options.url || 'wss://test.mosquitto.org/ws'; const clientId = `uniapp-client-${Math.random().toString(16).substr(2, 8)}`; client = mqtt.connect(url, { clientId, clean: true, reconnectPeriod: 1000, connectTimeout: 30 * 1000, username: options.username || '', password: options.password || '' }); // 处理连接成功事件 client.on('connect', () => { console.log('[MQTT] Connected'); }); // 处理断开连接事件 client.on('close', () => { console.warn('[MQTT] Disconnected'); }); // 处理错误事件 client.on('error', (err) => { console.error(`[MQTT Error]: ${err.message}`); }); } // 发布消息 function publish(topic, message) { if (!client || !client.connected) { console.error('[MQTT Publish Failed] Client not connected.'); return; } client.publish(topic, JSON.stringify(message), { qos: 0, retain: false }, (err) => { if (err) { console.error(`[MQTT Publish Error]: ${err.message}`); } else { console.log(`[MQTT Published to Topic "${topic}"]:`, message); } }); } // 订阅主题 function subscribe(topic, callback) { if (!client || !client.connected) { console.error('[MQTT Subscribe Failed] Client not connected.'); return; } client.subscribe(topic, { qos: 0 }, (err) => { if (err) { console.error(`[MQTT Subscribe Error]: ${err.message}`); } else { console.log(`[MQTT Subscribed to Topic "${topic}"]`); } }); // 设置接收消息回调函数 client.on('message', (receivedTopic, payload) => { try { const data = JSON.parse(payload.toString()); callback && callback(receivedTopic, data); } catch (e) { console.error(`[MQTT Parse Message Error]: ${e.message}`); } }); } export default { createMqtt, publish, subscribe }; ``` 上述代码实现了基本的消息发布与订阅功能[^2]。 --- #### 3. 初始化 MQTT 客户端 在全局生命周期钩子(如 App.vue)中调用 `createMqtt()` 方法以初始化客户端连接: ```javascript <template> </template> <script> import { createMqtt } from '@/utils/sendMqtt.js'; export default { onLaunch() { createMqtt({ url: 'ws://broker.hivemq.com:8000/mqtt', username: '', // 可选参数 password: '' // 可选参数 }); }, } </script> ``` 此部分负责建立初始连接[^1]。 --- #### 4. 页面中的数据处理 在具体的页面组件中,可以通过调用工具类的方法完成订阅与消息接收的操作。例如: ```javascript <template> <view>{{ receivedMessage }}</view> </template> <script> import { subscribe } from '@/utils/sendMqtt.js'; export default { data() { return { receivedMessage: '' }; }, onLoad() { subscribe('$SYS/brokers/+/clients/#', this.receiveCallback); // 替换为目标 topic }, methods: { receiveCallback(topic, message) { console.log(`Received message on topic "${topic}":`, message); this.receivedMessage = `${topic}: ${JSON.stringify(message)}`; } } }; </script> ``` 当有新消息到达时,会触发指定的回调函数并将数据显示在界面上[^3]。 --- #### 5. 测试与调试 测试过程中需注意以下几点: - 确认 WebSocket URL 是否可用; - 验证用户名密码配置是否匹配目标 Broker 要求; - 使用 Mosquitto CLI 或其他工具模拟发送消息至同一主题验证收发效果。 --- ### 总结 以上即是在 UniApp 中基于 `MQTT.js` 实现消息通信的核心步骤。通过合理封装工具类可有效提升代码复用性和维护效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值