mqtt宝典

mqtt简介

MQTT(Message Queuing Telemetry Transport)是一种轻量级的、开放式的消息传输协议,专门设计用于受限设备之间的通信,特别适用于物联网(IoT)环境。以下是 MQTT 的一些关键特点和概念:

轻量级: MQTT 是一种轻量级协议,它的设计简单而高效,适用于资源受限的设备,如传感器、嵌入式设备等。
发布/订阅模式: MQTT 使用发布/订阅模式进行通信。发布者(Publisher)将消息发布到特定的主题(Topic),而订阅者(Subscriber)则通过订阅特定的主题来接收消息。这种模式使得设备可以解耦通信,不需要直接知道彼此的存在,从而提高了系统的灵活性和可扩展性。
QoS级别: MQTT 提供了三个不同的服务质量(Quality of Service,QoS)级别,用于控制消息传输的可靠性和顺序性。这些级别分别是:
QoS 0:最多一次交付,消息不会被确认,可能会丢失或重复。
QoS 1:至少一次交付,确保消息至少被传输一次,但可能会重复。
QoS 2:恰好一次交付,确保消息被准确地传输一次,不会重复。
保留消息: MQTT 支持保留消息功能,允许发布者发布带有保留标志的消息,这些消息将会被保留在代理服务器(Broker)中,并在订阅者订阅相应主题时立即发送给它们。这对于设备在启动时获取最新状态或配置信息非常有用。
遗嘱消息: 发布者可以设置遗嘱消息,当发布者与 MQTT 代理断开连接时,代理将会发布这条遗嘱消息到指定的主题,通知其他订阅者发布者的离线状态。
可靠性和安全性: MQTT 提供了一些机制来确保通信的可靠性和安全性,如用户名/密码认证、TLS/SSL 加密通信等。
多种实现和广泛支持: MQTT 有多种开源实现,如 Eclipse Paho、Mosquitto 等,并且得到了广泛的支持和应用,包括在工业自动化、智能家居、物联网、传感器网络等领域。
总之,MQTT 是一种简单、轻量级、可靠的消息传输协议,适用于连接各种设备和系统的通信,并已成为物联网领域中的重要技术之一。

mqtt通配符

通配符+

+符号表示匹配一个级别内的任意字符,不能匹配多级别的主题。

通配符#

#符号表示匹配任意级别内的任意字符,可以匹配多级别的主题。

websocket实现mqtt效果

https://blog.csdn.net/u012643122/article/details/127539130

前端

package.json

stomp

	"dependencies": {
    	"stompjs": "^2.3.3",
    },

mqtt

	"dependencies": {
    	"mqtt": "^3.0.0",
    },

前端vue2使用stomp的方式:

// mq  websocket协议
import Cookies from "js-cookie";
import Stomp from 'stompjs';
import {MQTT_URL,MQTT_topic,MQTT_USERNAME,MQTT_PASSWORD} from '@/utils/mqConfig'

export default {
    components: { SidebarItem, Logo },
    data() {
        return {
            msgList: [],
            // 连接
            ws: null,
            count: 0,
            timer: null,
            inCon: false,
            timeout: null,
            client: Stomp.client(MQTT_URL),
            time: new Date().getTime()
        }
    },
    methods: {
        connect:function(){
            const headers = {
                login: MQTT_USERNAME,
                password: MQTT_PASSWORD
            };
            this.inCon = true
            this.client.connect(MQTT_USERNAME, MQTT_PASSWORD,this.onConnected,this.onFailed,'/');
            this.client.debug=false;
        },
        onConnected:function(){
            let user = this.$store.state.user.name;
            console.log('mq连接成功'+user)
            if (user) {
                // user = JSON.parse(user)
                //订阅的频道
                const topic = MQTT_topic+"-" + user;
                console.log("MQ topic:" + topic);
                this.client.subscribe(topic,this.responseCallback,this.onFailed);
                console.log('mq订阅成功')
            }

            if (this.timer) {
                clearInterval(this.timer)
                this.timer = null
                this.count = 0
            }

            this.inCon = false
        },
        onFailed:function(msg){
            console.log("MQ Failed:" + msg);
            this.inCon = false
            this.reconnectWSConnection()
	    },
        reconnectWSConnection () {
            let that = this
            if (this.timer === null) {
                this.timer = setInterval(() => {
                    if (this.count === 60) {
                        console.log('ws重连30分钟未成功,请刷新页面')
                        clearInterval(that.timer)
                        return
                    }
                    console.log('正在重连mqtt')
                    if (!that.inCon) {
                        that.inCon = false
                        that.ws = new WebSocket(MQTT_URL)
                        that.client = Stomp.over(that.ws)
                        that.client.connect(MQTT_USERNAME, MQTT_PASSWORD,this.onConnected,this.onFailed,'/');
                    }
                    that.count++
                }, 5000)
            }
        },
        handleDownload(row) {
            this.download('system/exportRecord/download/'+row.exportRecordId, {}, row.fileName);
        },
        //成功时的回调函数
        responseCallback:function(resp){
            try {
                debugger
                //接收消息的处理
                if (resp.body.indexOf('{') >= 0) {
                    console.log("MQ msg=>" + resp.body);
                    let res = JSON.parse(resp.body)
                    let type = res.type;
                    let code = res.code;
                    let time = res.time;
                    let msg = res.msg;
                    let title = res.title;
                    let data = res.data;
                    if(type=="importResult"){
                        this.$notify({
                            type: code==200?'success':'error',
                            title: this.$t("common.import")+title+this.$t(code==200?"common.success":"common.fail"),
                            dangerouslyUseHTMLString: true,
                            message: '<div style="width=120px;word-break:break-all;word-wrap:break-word;">'+'"'+data.fileName+'"'+msg+'</div>',
                            position: 'bottom-right',
                            duration: 0
                        });
                    }else if(type=="importProgress"){
                    }else if(type=="repSourceCodeResult"){
                        let me=this;
                        let downloadUrl='/system/exportRecord/download/'+data.exportRecordId;
                        let notifyObj=this.$notify({
                            type: code==200?'success':'error',
                            title: title,
                            dangerouslyUseHTMLString: true,
                            message: '<div style="width=120px;word-break:break-all;word-wrap:break-word;">'+'"'+data.fileName+'"'+msg+'</div>'+'<a href="javascript:void(0);">下载</a>',
                            position: 'bottom-right',
                            duration: 0,
                            onClick:function(){
                                me.$router.push('/exim/exportRecord?id='+data.exportRecordId);
                                me.handleDownload(data);
                                notifyObj.close();
                            },
                        });
                    }else if(type=="repSourceCodeProgress"){
                    }
                }
            } catch (error) {
                debugger
                console.error(error);
            }
	    },
    },
    computed: {
        ...mapState(["settings"]),
        ...mapGetters(["sidebarRouters", "sidebar"]),
        activeMenu() {
            const route = this.$route;
            const { meta, path } = route;
            // if set path, the sidebar will highlight the path you set
            if (meta.activeMenu) {
                return meta.activeMenu;
            }
            return path;
        },
        showLogo() {
            return this.$store.state.settings.sidebarLogo;
        },
        variables() {
            return variables;
        },
        isCollapse() {
            return !this.sidebar.opened;
        }
    },
    mounted() {
        this.connect();
    },
};

前端vue2使用mqtt的方式:

// mq  websocket协议
import mqtt from 'mqtt';

import {MQTT_URL,MQTT_topic,MQTT_USERNAME,MQTT_PASSWORD} from '@/utils/mqConfig'

export default {
    components: { SidebarItem, Logo },
    data() {
        return {
        }
    },
    methods: {
        connect:function(){
            const clientId = 'mqttjs_' + Math.random().toString(16).substr(2, 8)
            const host = MQTT_URL
            const options = {
                keepalive: 60,
                username: MQTT_USERNAME,
                password: MQTT_PASSWORD,
                clientId: clientId,
                protocolId: 'MQTT',
                protocolVersion: 4,
                clean: true,
                reconnectPeriod: 1000,
                connectTimeout: 30 * 1000,
                will: {
                    topic: 'WillMsg',
                    payload: 'Connection Closed abnormally..!',
                    qos: 0,
                    retain: false
                },
            }
            console.log('连接中')
            const client = mqtt.connect(host, options)

            client.on('error', (err) => {
                console.log('连接错误: ', err)
                client.end()
            })

            client.on('reconnect', () => {
                console.log('重连...')
            })

            client.on('connect', () => {
                console.log('已连接:' + clientId)
                // Subscribe
                let user = this.$store.state.user.name;
                if (user) {
                    const topic = MQTT_topic+"-" + user;
                    console.log("MQ topic:" + topic);
                    client.subscribe(topic, { qos: 0 })
                    console.log('mq订阅成功')
                    client.on('message', (topic, message, packet) => {
                        console.log(topic+">>>mq接收到消息:"+(typeof message)+">>>"+message)
                        this.responseCallback(message);
                    })
                }

                
            })
        },
        handleDownload(row) {
            this.download('system/exportRecord/download/'+row.exportRecordId, {}, row.fileName);
        },
        //成功时的回调函数
        responseCallback:function(resp){
            try {
                debugger
                //接收消息的处理
                if (resp.indexOf('{') >= 0) {
                    console.log("MQ msg=>" + resp);
                    let res = JSON.parse(resp)
                    let type = res.type;
                    let code = res.code;
                    let time = res.time;
                    let msg = res.msg;
                    let title = res.title;
                    let data = res.data;
                    if(type=="importResult"){
                        this.$notify({
                            type: code==200?'success':'error',
                            title: this.$t("common.import")+title+this.$t(code==200?"common.success":"common.fail"),
                            dangerouslyUseHTMLString: true,
                            message: '<div style="width=120px;word-break:break-all;word-wrap:break-word;">'+'"'+data.fileName+'"'+msg+'</div>',
                            position: 'bottom-right',
                            duration: 0
                        });
                    }else if(type=="importProgress"){
                    }else if(type=="repSourceCodeResult"){
                        let me=this;
                        let downloadUrl='/system/exportRecord/download/'+data.exportRecordId;
                        let notifyObj=this.$notify({
                            type: code==200?'success':'error',
                            title: title,
                            dangerouslyUseHTMLString: true,
                            message: '<div style="width=120px;word-break:break-all;word-wrap:break-word;">'+'"'+data.fileName+'"'+msg+'</div>'+'<a href="javascript:void(0);">下载</a>',
                            position: 'bottom-right',
                            duration: 0,
                            onClick:function(){
                                me.$router.push('/exim/exportRecord?id='+data.exportRecordId);
                                me.handleDownload(data);
                                notifyObj.close();
                            },
                        });
                    }else if(type=="repSourceCodeProgress"){
                    }
                }
            } catch (error) {
                debugger
                console.error(error);
            }
	    },
    },
    computed: {
        ...mapState(["settings"]),
        ...mapGetters(["sidebarRouters", "sidebar"]),
        activeMenu() {
            const route = this.$route;
            const { meta, path } = route;
            // if set path, the sidebar will highlight the path you set
            if (meta.activeMenu) {
                return meta.activeMenu;
            }
            return path;
        },
        showLogo() {
            return this.$store.state.settings.sidebarLogo;
        },
        variables() {
            return variables;
        },
        isCollapse() {
            return !this.sidebar.opened;
        }
    },
    mounted() {
        this.connect();
    },
};

前端微信小程序使用mqtt的方式:


import {MQTT_URL,MQTT_USERNAME,MQTT_PASSWORD} from '@/utils/mqConfig'

let client = null
// 引入MQTT(也是要npm install mqtt的)
import mqttInfo from 'mqtt/dist/mqtt.js'

// 连接方法
export default {
	/**
	 *订阅多个subscribe传入字符串数组
	 */
	init(userId, subscribe, fun){
		let options = {
			username: MQTT_USERNAME,
			password: MQTT_PASSWORD,
			clientId: 'WX-' + userId,
			connectTimeout: 600000,
			clean: false,
      		reconnectPeriod: 5000,
		}
		
		if(client){
			// 多个页面都有使用mqtt时,不能重复连接, 需关闭后再连接
			client.end()
			client = null
			setTimeout(() => {
				this.connect(options, subscribe, fun)
			}, 500)
		} else {
			this.connect(options, subscribe, fun)
		}
	},
	connect(options, subscribe, fun) {
		// 主要是ws和wx
		// #ifdef H5
		//h5的连接是 'ws://' + url。
		client = mqttInfo.connect('wss://' + MQTT_URL, options)
		// #endif
		// #ifdef MP-WEIXIN || MP-ALIPAY || APP-PLUS
		//app的连接是 'wx://' + url。
		client = mqttInfo.connect('wxs://' + MQTT_URL, options)
		// #endif
		client.on('connect', (res)=>{
			if (client) {
				client.subscribe(subscribe , (err)=>{
					console.log('订阅主题:' + subscribe)
					if (!err) {  
						console.log('订阅主题成功')
					}  
				})
			} else {
				console.log('client 对象为空,无法订阅主题。')
			}
		})
		
		// mqtt离线
		client.on('offline', function() {
			console.log('offline')
		})
		
		//mqtt接收到信息
		client.on('message', function(topic, message) {
			console.log('mqtt接收到数据:' + message)
			let msg = JSON.parse(message.toString())
			if (fun) {
				fun(msg)
			}
		})
		
		//mqtt连接失败
		client.on('error', (err) => {
			console.log('error', err)
			//重新连接
			client.reconnect()
		})
		//mqtt断开连接回调
		client.on('close', (err) => {
			console.log('close', err)
		})
	},
	close() {
		if(client) {
			console.log('关闭订阅')
			client.end()
			client = null
		}
	}
}

前端原生js使用mqtt的方式:

function connect() {
	const clientId = 'mqttjs_' + Math.random().toString(16).substr(2, 8)
	const host = 'wss://'+domain+'/mqtt'
	const options = {
		keepalive: 60,
		username: "xxx",
		password: "xxx",
		clientId: clientId,
		protocolId: 'MQTT',
		protocolVersion: 4,
		clean: true,
		reconnectPeriod: 1000,
		connectTimeout: 30 * 1000,
		will: {
			topic: 'WillMsg',
			payload: 'Connection Closed abnormally..!',
			qos: 0,
			retain: false
		},
	}
	console.log('连接中')
	const client = mqtt.connect(host, options)

	client.on('error', (err) => {
		console.log('连接错误: ', err)
		client.end()
	})

	client.on('reconnect', () => {
		console.log('重连...')
	})

	client.on('connect', () => {
		console.log('已连接:' + clientId)
		// Subscribe
		client.subscribe('your/topic/#', { qos: 0 })
		client.on('message', (topic, message, packet) => {
			console.log('收到消息:' + message.toString() + '\nOn topic: ' + topic)
			var result = JSON.parse(message.toString());
			
		})
	})

}

后台

pom.xml

rabbitmq

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-amqp</artifactId>
                <version>2.3.12.RELEASE</version>
            </dependency>

spring-mqtt

spring-integration-mqtt已包含了org.eclipse.paho.client.mqttv3

            <dependency>
                <groupId>org.springframework.integration</groupId>
                <artifactId>spring-integration-mqtt</artifactId>
                <version>5.5.19</version>
            </dependency>

paho-mqtt

        <dependency>
            <groupId>org.eclipse.paho</groupId>
            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
            <version>1.2.5</version>
        </dependency>

代码

后台使用rabbitmq+mqtt插件的方式1:

import com.alibaba.fastjson.JSONObject;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class TcpClientSendMQ {

    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void sendDataToWeb(TaskType taskType, String username, String title, String code,String msg,Object data) {
        JSONObject json = new JSONObject();
        json.put("type",taskType.getValue());
        json.put("code",code);
        json.put("time",System.currentTimeMillis());
        json.put("msg",msg);
        json.put("title",title);
        json.put("data",data);
        rabbitTemplate.convertAndSend(RabbitConfig.QUEUE_CMS_WEB_MSG +"-"+ username, JSONObject.toJSONString(json));
    }
    public void sendMsgToWeb(TaskType taskType, String username, String fileName, String title, String code, String msg) {
        JSONObject data = new JSONObject();
        data.put("fileName",fileName);
        sendDataToWeb(taskType,username,title,code,msg,data);
    }
}

后台使用rabbitmq+mqtt的方式2:

import com.alibaba.fastjson.JSONObject;
import com.omni.common.config.MqttSender;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class TcpClientSendMQ {

    @Autowired
    private MqttSender mqttSender;

    public void sendDataToWeb(TaskType taskType, String username, String title, String code,String msg,Object data) {
        JSONObject json = new JSONObject();
        json.put("type",taskType.getValue());
        json.put("code",code);
        json.put("time",System.currentTimeMillis());
        json.put("msg",msg);
        json.put("title",title);
        json.put("data",data);
        mqttSender.sendWithTopicAndQos(RabbitConfig.QUEUE_CMS_WEB_MSG +"-"+ username, 0, JSONObject.toJSONString(json));
    }
    public void sendMsgToWeb(TaskType taskType, String username, String fileName, String title, String code, String msg) {
        JSONObject data = new JSONObject();
        data.put("fileName",fileName);
        sendDataToWeb(taskType,username,title,code,msg,data);
    }
}

后台使用mqtt工具类(脱离spring,实现连接多mqtt地址):

https://blog.csdn.net/u012643122/article/details/132326165

nginx配置rabbitmq+mqtt插件

		location /mqtt {
			root /usr/share/nginx/html;
			proxy_pass http://127.0.0.1:15674; # 代理rabbitmq
			proxy_http_version 1.1;
			proxy_connect_timeout 500;
            proxy_read_timeout 500;
            proxy_send_timeout 500;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
	    }

nginx配置rabbitmq+emqx

		location /mqtt {
			root /usr/share/nginx/html;
			proxy_pass http://127.0.0.1:8083/mqtt; # 代理emqx
			proxy_http_version 1.1;
			proxy_connect_timeout 500;
            proxy_read_timeout 500;
            proxy_send_timeout 500;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
	    }

emqx开启微信mqtt支持

docker exec -it -uroot emqx bash
echo "listeners.ws.default.websocket.fail_if_no_subprotocol = false" >> ./etc/emqx.conf

rabbitmq和emqx的安装

https://blog.csdn.net/u012643122/article/details/133869648

mqtt客户端

1.MQTT.FX

2.MQTTX

3.MQTT Explorer

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Proteus是一款电子电路仿真软件,可以用于设计、测试和验证电路原理图和PCB布局。而MQTT是一种轻量级的通信协议,用于物联网设备之间的消息传递。 在Proteus中使用MQTT,可以模拟物联网设备之间的通信。你可以使用MQTTBox或者编写代码来代替MQTT工具。首先,你需要在Proteus中添加一个虚拟串口工具(vspdpro.exe),用于模拟串口通信。然后,你可以在Proteus中添加一个TCP接收工具(通讯猫),用于接收MQTT消息。接下来,你可以使用Proteus提供的函数或者编写代码来实现MQTT的功能。 以下是一个使用Proteus和MQTT的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> // 定义MQTT消息处理函数 void mqtt_message_handler(char* topic, char* message) { printf("Received MQTT message:\n"); printf("Topic: %s\n", topic); printf("Message: %s\n", message); } int main() { // 初始化Proteus和MQTT Proteus_Init(); MQTT_Init(); // 订阅MQTT主题 MQTT_Subscribe("topic1"); MQTT_Subscribe("topic2"); // 设置MQTT消息处理函数 MQTT_SetMessageHandler(mqtt_message_handler); // 运行Proteus和MQTT Proteus_Run(); MQTT_Run(); return 0; } ``` 在上面的示例代码中,我们首先初始化Proteus和MQTT。然后,我们订阅了两个MQTT主题。接下来,我们设置了一个MQTT消息处理函数,用于处理接收到的MQTT消息。最后,我们运行了Proteus和MQTT。 请注意,上述示例代码仅为演示目的,实际使用时需要根据具体情况进行修改和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值