前端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(Message Queuing Telemetry Transport)是一种轻量级的通信协议,用于在低带宽和不稳定的网络环境下,实现物联网设备之间的即时通信。前端可以使用MQTT来订阅消息,以获取实时的数据更新。 首先,我们需要引入MQTT的客户端库。一般来说,我们可以使用开源的Paho MQTT客户端库来实现。可以通过直接下载js文件,或者使用npm安装。 接下来,我们需要创建一个MQTT的客户端实例。通过指定MQTT broker的地址、端口和协议,我们可以建立与broker的连接。同时,我们还需要指定一个client ID,用于标识当前的客户端。 一旦连接建立成功,我们可以通过使用subscribe()方法来订阅特定的主题(topic)。主题可以看做是一种消息的分类或者标签。当有新的消息发布到这个主题上时,前端会收到相应的消息回调。 在订阅成功后,前端就可以接收到来自broker的实时消息了。前端可以定义一个回调函数,用于处理接收到的消息。这个回调函数可以根据消息的内容,更新页面上的相关数据或者执行相应的操作。 如果前端不再需要订阅某个主题,可以使用unsubscribe()方法来取消订阅。 需要注意的是,由于前端是在浏览器中运行的,它的网络连接通常是不稳定的。因此,在实际应用中,我们一般会在连接断开时,尝试重新连接,以确保能够持续接收到实时消息。 总的来说,前端通过MQTT订阅消息,可以实现实时数据的获取和展示,在物联网应用、实时监控等场景中有着广泛的应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值