在vue使用MQTT

在vue使用MQTT

最近有个需求,需要前端直接链接mqtt,想到后面可能多出使用,就封装成了hooks

中间遇到了一个坑,就是浏览器默认不支持mqtt协议,其借助了webSocket实现的mqtt协议,
而mqtt默认未开启webSocket官网中并说明,但其demo中都是使用的ws,最后通过不断的摸索确认是
需要在配置中进行相关配置

安装mqtt插件

pnpm add mqtt

or

npm i mqtt

or

yarn add mqtt

导入mqtt

import * as mqtt from "mqtt/dist/mqtt.min"

封装

这个封装只需要稍加改动就能在react中使用

import * as mqtt from "mqtt/dist/mqtt.min";
import {onUnmounted, reactive, ref} from "vue";

export default function useMqtt(options, getMessage) {
    const data = ref();
     if (!['accept', 'send'].includes(options.type )) {
        throw new Error('options.type must be in \'accept\', \'send\'')
    }
    
    const connection = reactive({
        type: options.type ?? 'accept',
        protocol: options.host ?? 'ws',
        host: options.host ?? '81.69.203.93',
        port: options.port ?? 8083,
        clientId: options.clientId ?? "mqttx_" + Math.random().toString(16).substring(2, 8),
        username: options.username ?? 'health_iot',
        password: options.password ?? '123456',
        clean: options.clean ?? true,
        connectTimeout: options.connectTimeout ?? 30 * 1000, // ms
        reconnectPeriod: options.reconnectPeriod ?? 4000 // ms
    });
    /**
     * 订阅信息设置
     */
    const subscription = ref({
        topic: options.subscription.topic, //需要动态配置
        qos: options.subscription.qos,
        topicPrefix: options.subscription.topicPrefix
    });
    let client = ref({
        connected: false
    });
    const receivedMessages = ref("");
    const subscribedSuccess = ref(false);
    const btnLoadingType = ref("");
    const retryTimes = ref(0);
    /**
     * 初始化
     */
    const initData = () => {
        client.value = {
            connected: false
        };
        retryTimes.value = 0;
        btnLoadingType.value = "";
        subscribedSuccess.value = false;
    };
    const handleOnReConnect = () => {
        console.log(`${retryTimes.value}次重试`);
        retryTimes.value += 1;
        if (retryTimes.value > 5) {
            try {
                client.value.end();
                initData();
            } catch (error) {
                console.error(error)
            }
        }
    };
    /**
     * 创建连接
     */
    const createConnection = () => {
        try {
            btnLoadingType.value = "connect";
            const {protocol, host, port, ...options} = connection;
            const connectUrl = `${protocol}://${host}:${port}/mqtt`;
            client.value = mqtt.connect(connectUrl, options);
            if (client.value.on) {
                client.value.on("connect", () => {
                    btnLoadingType.value = "";
                    console.log("------链接建立成功------");
                });
                client.value.on("reconnect", handleOnReConnect);
                client.value.on("error", (error) => {
                    console.error("------链接建立失败------", error)
                });
                client.value.on("message", (topic, message) => {
                    receivedMessages.value = receivedMessages.value.concat(message.toString());
                    data.value = JSON.parse(message);
                    if (getMessage) getMessage(message);
                    console.log("收到的数据--------------", data.value);
                });
            }
        } catch (error) {
            btnLoadingType.value = "";
            console.error("链接出错", error);
        }
    };
    /**
     * 订阅消息
     */
    const doSubscribe = () => {
        const {topic, qos, topicPrefix} = subscription.value;
        if (connection.type === 'send') {
            console.error('前type:send,禁止订阅消息:',topic)
            return
        }
        btnLoadingType.value = "subscribe";
        client.value.subscribe(`${topicPrefix}${topic}`, {qos}, (error, granted) => {
            btnLoadingType.value = "";
            if (error) {
                console.log("subscribe error:", error);
                return;
            }
            subscribedSuccess.value = true;
            console.log("subscribe successfully:", granted);
        });
    };
    /**
     * 关闭连接
     */
    const destroyConnection = () => {
        if (client.value.connected) {
            btnLoadingType.value = "disconnect";
            try {
                client.value.end(false, () => {
                    initData();
                    console.log("disconnected successfully");
                });
            } catch (error) {
                btnLoadingType.value = "";
                console.log("disconnect error:", error);
            }
        }
    };
    /**
     * 发送消息
     * @param data
     */
    const publishMessage = (data) => {
        const {topic, qos} = subscription.value
        if (connection.type === 'accept') {
            console.error('前type:accept,禁止发送消息',topic)
            return
        }
        btnLoadingType.value = "publish";
        console.log(`发送消息到【${topic}】-【${qos}`)
        client.value.publish(`${topic}`, data, {qos}, (error) => {
            btnLoadingType.value = "";
            if (error) {
                console.error("消息发送失败", error);
                return;
            }
            console.log(`消息内容${data}`);
        });
    };

    /**
     * 取消订阅
     */
    const doUnSubscribe = () => {
        btnLoadingType.value = "unsubscribe";
        const {topic, qos, topicPrefix} = subscription.value;
        console.warn("取消订阅------->", `${topicPrefix}${topic}`, qos);
        client.value.unsubscribe(`${topicPrefix}${topic}`, {qos}, (error) => {
            btnLoadingType.value = "";
            subscribedSuccess.value = false;
            if (error) {
                console.log("unsubscribe error:", error);
                return;
            }
            console.log(`unsubscribed topic: ${topic}`);
        });
    };
    /**
     * 创建连接并订阅
     */
    const createAndDo = () => {
        createConnection();
        if (connection.type === 'accept')doSubscribe();
    }
    // //组件销毁前断开连接
    onUnmounted(() => {
        console.log("------页面销毁前断开连接------");
        destroyConnection();
    });
    return {
        data,
        publishMessage,
        connection,
        subscription,
        doUnSubscribe,
        destroyConnection,
        createConnection,
        doSubscribe,
        createAndDo
    };
}
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万水千山走遍TML

您的鼓励,将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值