前端MQTT详细使用的两种方法

 更新时间:2024年07月24日 08:28:39   作者:CV工程师!!  
MQTT(消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的通讯协议,该协议构建于TCP/IP协议上,这篇文章主要给大家介绍了关于前端MQTT详细使用的两种方法,需要的朋友可以参考下

首先

npm install mqtt --save

一,.第一种方法 (相对比较容易看懂) 

使用场景跟MQTTX 类似的测试调试订阅接收信息的工具 (参数都是可配置的)

1.1 新建 mqtt.js

import * as mqtt from "mqtt/dist/mqtt.min";
import { ElMessage } from 'element-plus'
class MQTT {
    url = '';// mqtt地址
    topic = ''; //
    clientId = '';
    username = '';
    password = '';//密码
    qos = 0;
    // 初始化类实例
    constructor(params) {
        this.topic = params.topic;
        this.url = params.url;
        // 虽然是mqtt但是在客户端这里必须采用websock的链接方式
        this.clientId = params.clientId;
        this.username = params.username;
        this.password = params.password;
        this.qos = params.qos;
    }

    //初始化mqtt
    init() {
        const options = {
            // protocol: "ws",
            // host: this.url,
            // ws: 8083; wss: 8084
            // port: 8083,
            // endpoint: "/mqtt",
            clean: true,
            connectTimeout: 4000, // 超时时间
            username: this.username,
            password: this.password,
            clientId: this.clientId,
            clean: true,
            connectTimeout: 30 * 1000, // ms
            reconnectPeriod: 4000, // ms
        };
//ws://localhost:8083/mqtt  这里组合起来是这种格式的地址 但是我传递过来的地址直接就是完整地址不用组装 所以我才注释上面 options 中的参数 
        const connectUrl = `${options.protocol}://${options.host}:${options.port}${options.endpoint}`;
//并在这里直接使用地址链接
        this.client = mqtt.connect(this.url, options);
        // 消息处理
        this.client.on("message", (topic, message) => {
            // console.log("收到消息", topic, message);
            // console.log("收到消息" + topic + '发来的' + JSON.parse(message));
        })
        // 重连处理
        this.client.on('reconnect', (error) => {
            console.log('正在重连:', error)
        });
        // 链接失败
        this.client.on('error', (error) => {
            console.log(error);
        });
    }
    //取消订阅
    unsubscribes() {
        this.client.unsubscribe(this.topic, (error) => {
            if (!error) {
                console.log('取消订阅成功');
            } else {
                // console.log('取消订阅失败');
            }
        });
    }
    //连接
    link() {
        this.client.on('connect', (con) => {
            let qosValue = this.qos
            this.client.subscribe(this.topic, { qosValue }, (error, res) => {
                if (!error) {
                    console.log('订阅成功');
                    ElMessage({
                        message: '订阅成功',
                        type: 'success',
                    })
                } else {
                    ElMessage({
                        message: '订阅失败',
                        type: 'error',
                    })
                    // console.log('订阅失败');
                }
            });
        });
    }
    // 发送信息
    SendMessage(topic, sendMsg) {
        let options = this.qos
        this.client.publish('rscu/sensor/exterior/up/id', sendMsg, options, (err, a) => {
            if (!err) {
                console.log('发送信息成功');
                ElMessage({
                    message: '发送信息成功',
                    type: 'success',
                })
            } else {
                console.log('发送信息失败');
            }
        })
    }
    //收到的消息
    get(callback) {
        this.client.on('message', callback);
    }
    //结束链接
    over() {
        this.client.end();
        console.log('结束链接');
    }
}
export default MQTT;

1.2 新建useMqtt.js (当时与对上面 mqtt.js的使用并二次封装)

import MQTT from './mqtt';
import { onUnmounted, ref } from 'vue';
import { ElMessage } from 'element-plus'
export default function useMqtt() {
    const PublicMqtt = ref(null);

    const startMqtt = (val, callback) => {

        //设置订阅地址
        PublicMqtt.value = new MQTT(val);
        //初始化mqtt
        PublicMqtt.value.init();
        //链接mqtt
        PublicMqtt.value.link();
        getMessage(callback);
    };
    // 发送信息 监测有没有链接 没有弹框
    const send = (topic, message) => {
        if (PublicMqtt.value) {
            let mqttPayload = JSON.parse(message);
            mqttPayload.dynamicType = "";
            message = JSON.stringify(mqttPayload);
            PublicMqtt.value.SendMessage(topic, message);
        } else {
            ElMessage({
                message: '尚未连接',
                type: 'error',
            });
        }
    }
    const getMessage = (callback) => {
        PublicMqtt.value?.get(callback);
    };
    // 断开链接
    const endMqtt = () => {
        if (PublicMqtt.value) {
            PublicMqtt.value.unsubscribes();
            PublicMqtt.value.over();
        }
    }
    onUnmounted(() => {
        //页面销毁结束订阅
        if (PublicMqtt.value) {
            PublicMqtt.value.unsubscribes();
            PublicMqtt.value.over();
        }
    });

    return {
        startMqtt,
        send,
        endMqtt
    };
}

1.3页面使用

import useMqtt from '../../../utils/useMqtt'
const { startMqtt, send, endMqtt } = useMqtt();

//链接 订阅 方法  在需要的地方调用  (参数可看第一张效果图上的参数)
function ConcatMqttFn() {
//校验输入信息
    protocolForm.value.validate((valid) => {
        if (valid) {
            let params = {
                topic: protocolFormData.topic,   //主题  
                url: protocolFormData.addressPath, //地址
                clientId: protocolFormData.clientId,  //clientId
                username: protocolFormData.account,   //用户名
                password: protocolFormData.password,  //密码
                qos: protocolFormData.qos,  //qos
            }
            startMqtt(params, (topic, message) => {
//因为我在封装js里面 callback 将他接收的信息返回回来了 所以我在这可以直接接收到
                const msg = JSON.parse(message.toString());
                requestData.value = msg
            });
        }
    })
}

//最后在需要关闭链接 取消订阅的地方使用   endMqtt() 方法

二,第二种方法 (适用于不用配置 全局固定死链接地址和订阅主题) 就一个js文件

2.1 新建allMqtt.js

import * as mqtt from "mqtt/dist/mqtt.min";
import { onUnmounted, ref, reactive } from 'vue';
import { ElNotification } from 'element-plus'
export default function useMqtt() {
    let client = ref({
        connected: false
    });
    const notifyPromise = ref(Promise.resolve())
    const qosList = [0, 1, 2];
    // 订阅主题
    const topic = ref('rscu/sensor/warning/count')
    // 发送主题
    const sendTopic = ref('rscu/sensor/warning')
    const qos = ref(1)
    // 链接地址
    const hostUrl = ref('')

//window.server.fileUploadUrl  这个是我在public文件下 static文件下 
//创建的config.js 中定义的一个全局静态地址 并在 index.html中引用了他 他不会被打包 
//你们也可以直接固定死
    hostUrl.value = window.server.fileUploadUrl ? window.server.fileUploadUrl : ''
    const connection = reactive({
        // 指明协议类型
        protocol: "ws",
        host: hostUrl.value,
        // ws: 8083; wss: 8084
        port: 8083,
        endpoint: "/mqtt",
        // for more options, please refer to https://github.com/mqttjs/MQTT.js#mqttclientstreambuilder-options
        clean: true,
        connectTimeout: 30 * 1000, // ms
        reconnectPeriod: 4000, // ms
        clientId: "emqx_benYing_" + Math.random().toString(16).substring(2, 8),
        // auth
        username: "warning",
        password: "root",
    });
    const messageValue = ref(false)
    // 订阅的信息
    const receiveNews = ref('')
    const time = ref(null)
    const startMqtt = (topic, callback) => {
        try {
            const { protocol, host, port, endpoint, ...options } = connection;
            const connectUrl = `${protocol}://${host}:${port}${endpoint}`;
            client.value = mqtt.connect(connectUrl, options);
            if (client.value.on) {
                // 连接
                client.value.on("connect", () => {
                    console.log("连接成功 successful");
                    link()
                });
                // 重连
                client.value.on("reconnect", handleOnReConnect);
                client.value.on("error", (error) => {
                    // console.log("重连失败 error:", error);
                });
                // 收到信息 callback返回收到的信息
                client.value.on("message", callback);
            }
        } catch (error) {
            // console.log("mqtt.connect error:", error);
        }
    };
    // 订阅
    const link = () => {
        client.value.subscribe(
            topic.value,
            '1',
            (error, granted) => {
                if (error) {
                    // console.log("订阅失败 error:", error);
                    return;
                } else {
                    sendMessage()
                    // console.log("订阅成功 successfully:", granted);
                }
            }
        );
    };
    // 取消订阅
    const UnSubscribe = () => {
        let qosValue = qos.value
        client.value.unsubscribe(topic.value, { qosValue }, (error) => {
            if (error) {
                // console.log("取消订阅失败 error:", error);
                return;
            }
            console.log(`取消订阅成功 topic: ${topic}`);
        });
    };
    // 取消连接
    const destroyConnection = () => {
        if (client.value.connected) {
            try {
                client.value.end(false, () => {
                    console.log("断开连接成功 successfully");
                });
            } catch (error) {
                // console.log("断开连接失败 error:", error);
            }
        }
    };

    const retryTimes = ref(0);
    const handleOnReConnect = () => {
        retryTimes.value += 1;
        if (retryTimes.value > 5) {
            try {
                client.value.end();
                initData();
                // console.log("connection maxReconnectTimes limit, stop retry");
            } catch (error) {
                // console.log("handleOnReConnect catch error:", error);
            }
        }
    };
    const initData = () => {
        client.value = {
            connected: false,
        };
        retryTimes.value = 0;
    };
//发送信息
    const sendMessage = () => {
        client.value.publish('rscu/sensor/warning', '1', '1', (err, a) => {
            if (!err) { } else {

            }
        })
    };

    return {
        startMqtt,
        link,
        UnSubscribe,
        destroyConnection,
        sendMessage
    };
}

2.2使用

// 使用MQTT
import useMqtt from '../../utils/allMqtt.js'
const { startMqtt, link, UnSubscribe, destroyConnection } = useMqtt();

//html:
    <div class="message-prompt" :class="{ 'change': animateClass == true }">
                <el-dropdown trigger="click" @command="messageHandleCommand">
                    <span style="cursor: pointer;">
                        <el-badge :value="all" :max="99" class="item">
                            <el-icon color="#fff" size="20">
                                <Bell />
                            </el-icon>
                        </el-badge>
                    </span>
                    <template #dropdown>
                        <el-dropdown-menu>
                            <el-dropdown-item command="warning">
                                <span>预警</span>
                                <span class="warning-text num">{{ alarm }}</span>
                            </el-dropdown-item>
                            <el-dropdown-item command="alarm">
                                <span>报警</span>
                                <span class="alarm-text num">{{ warning }}</span>
                            </el-dropdown-item>
                            <el-dropdown-item command="all">
                                <span>查看全部</span>
                            </el-dropdown-item>
                        </el-dropdown-menu>
                    </template>
                </el-dropdown>
            </div>

//因为我在链接的时候 顺便调用了他的订阅方法 在js中 所以我在这直接链接
function ConcatMqttFn() {
    startMqtt('', (topic, message) => {
//拿到的数据
        const msg = JSON.parse(message.toString());
        // console.log(msg, 'msg');
        alarm.value = msg.data.alarm
        all.value = msg.data.all
        warning.value = msg.data.warning
    });
}

//生命周期销毁的时候 取消 断开
onMounted(() => {
    destroyConnection()
    ConcatMqttFn()
});

2.3实现效果

总结

到此这篇关于前端MQTT详细使用方法的文章就介绍到这了,更多相关前端MQTT使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

最新评论