Understanding and use of MQTT

MQTT is a lightweight protocol based on the publish/subscribe model, which is based on the TCP/IP protocol and released by IBM in 1999.
insert image description here

Process understanding: Subscribers will select a topic (Topic) and quality of service (QoS) when subscribing, and then the publisher will publish a message, and the agent will push different messages to relevant subscribers according to the topic.
Topic: Everyone's preferences, taking newspaper subscription as an example, are military, financial and other topics.
QoS: Transmission quality (agreed by the publisher and subscriber of the message), QoS0 (no matter after publishing, at most once), QoS1 (after sending, according to the specification, whether to start retransmission, so at least once), QoS2 (ensure only once )

Application scenario: This protocol is mainly used in the Internet of Things, because the overhead is small and the network requirements are not high. My usage scenario this time is the communication with the Android system and the return of positioning information.

1. MQTT dependency

Here is springboot integrated mqtt, so add it in pom.xml

<!--Mqtt依赖-->
<dependency>
	<groupId>org.springframework.integration</groupId>
	<artifactId>spring-integration-mqtt</artifactId>
</dependency>

2. MQTT client

setCleanSession indicates the session life cycle, the default is True. When it is true, it means to create a new session. When the client disconnects, the session will be destroyed automatically. When it is false, it means to create a persistent session, and the session will still be kept after the client disconnects (provided that the ClientID has not changed), until the session times out and logs out.

import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.stereotype.Component;

/**
 * 类描述:Mqtt连接工具类
 *
 * @ClassName MQTTConnect
 * @Author yeapt
 * @Date 2023-07-20 12:22
 */

@Component
public class MQTTConnect {
    
    
    //mqtt服务器的地址和端口号
    private String HOST = "tcp://192.168.1.113:123";
    private final String clientId = "DC" + (int) (Math.random() * 100000000);
    private MqttClient mqttClient;

    /**
     * 客户端connect连接mqtt服务器
     *
     * @param userName     用户名
     * @param passWord     密码
     * @param mqttCallback 回调函数
     **/
    public void setMqttClient(String userName, String passWord, MqttCallback mqttCallback) throws MqttException {
    
    
        MqttConnectOptions options = mqttConnectOptions(userName, passWord);
        if (mqttCallback == null) {
    
    
            mqttClient.setCallback(new Callback());
        } else {
    
    
            mqttClient.setCallback(mqttCallback);
        }
        mqttClient.connect(options);
    }

    /**
     * MQTT连接参数设置
     */
    private MqttConnectOptions mqttConnectOptions(String userName, String passWord) throws MqttException {
    
    
        mqttClient = new MqttClient(HOST, clientId, new MemoryPersistence());
        MqttConnectOptions options = new MqttConnectOptions();
        options.setUserName(userName);
        options.setPassword(passWord.toCharArray());
        //连接超时时间,默认:30
        options.setConnectionTimeout(10);
        //重连配置,默认:false
        options.setAutomaticReconnect(true);
        //会话生命周期,默认:true
        options.setCleanSession(true);
        //默认:60
        options.setKeepAliveInterval(60);
        return options;
    }

    /**
     * 关闭MQTT连接
     */
    public void close() throws MqttException {
    
    
        mqttClient.disconnect();
        mqttClient.close();
    }

    /**
     * 向某个主题发布消息 默认qos:1
     *
     * @param topic:发布的主题
     * @param msg:发布的消息
     */
    public void pub(String topic, String msg) throws MqttException {
    
    
        MqttMessage mqttMessage = new MqttMessage();
        //Qos2:保证消息至少传输成功1次
        mqttMessage.setQos(2);
        mqttMessage.setPayload(msg.getBytes());
        MqttTopic mqttTopic = mqttClient.getTopic(topic);
        MqttDeliveryToken token = mqttTopic.publish(mqttMessage);
        token.waitForCompletion();
    }

    /**
     * 向某个主题发布消息
     *
     * @param topic: 发布的主题
     * @param msg:   发布的消息
     * @param qos:   消息质量    Qos:0、1、2
     */
    public void pub(String topic, String msg, int qos) throws MqttException {
    
    
        MqttMessage mqttMessage = new MqttMessage();
        mqttMessage.setQos(qos);
        mqttMessage.setPayload(msg.getBytes());
        MqttTopic mqttTopic = mqttClient.getTopic(topic);
        MqttDeliveryToken token = mqttTopic.publish(mqttMessage);
        token.waitForCompletion();
    }

    /**
     * 订阅某一个主题 ,此方法默认的的Qos等级为:1
     *
     * @param topic 主题
     */
    public void sub(String topic) throws MqttException {
    
    
        mqttClient.subscribe(topic);
    }

    /**
     * 订阅某一个主题,可携带Qos
     *
     * @param topic 所要订阅的主题
     * @param qos   消息质量:0、1、2
     */
    public void sub(String topic, int qos) throws MqttException {
    
    
        mqttClient.subscribe(topic, qos);
    }
}

3. MQTT callback function

Used to handle business, how to deal with the information after getting it

import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;

/**
 * 类描述:MQTT回调
 *
 * @ClassName Callback
 * @Author yeapt
 * @Date 2023-07-20 12:24
 */
@Slf4j
public class Callback implements MqttCallback {
    
    
    /**
     * MQTT 断开连接会执行此方法
     */
    @Override
    public void connectionLost(Throwable throwable) {
    
    
        log.info("断开了MQTT连接 :{}", throwable.getMessage());
        log.error(throwable.getMessage(), throwable);
    }

    /**
     * publish发布成功后会执行到这里
     */
    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
    
    
        log.info("发布消息成功");
    }

    /**
     * subscribe订阅后得到的消息会执行到这里
     */
    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {
    
    
        //  TODO    此处可以将订阅得到的消息进行业务处理、数据存储
        log.info("收到来自 " + topic + " 的消息:{}", new String(message.getPayload()));
}}

4. Debugging and use

In the development stage, the main method is used for testing, but in actual use, the monitoring is generally turned on when the program starts.

/**
* main函数自己测试用
*/
public static void main(String[] args) throws MqttException {
    
    
  MQTTConnect mqttConnect = new MQTTConnect();
  mqttConnect.setMqttClient("admin", "password", new Callback());
  mqttConnect.sub("/abcd-trace/#",2);
  mqttConnect.pub("/abcd-trace/#", "Mr.Y" + (int) (Math.random() * 100000000));
    }
import com.stylefeng.guns.modular.xujianapi.util.mqtt.Callback;
import com.stylefeng.guns.modular.xujianapi.util.mqtt.MQTTConnect;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

/**
 * 类描述:MQTT监听类
 *
 * @ClassName MQTTListener
 * @Author yeapt
 * @Date 2023-07-20 12:27
 */
@Slf4j
@Component
public class MQTTListener implements ApplicationListener<ContextRefreshedEvent> {
    
    
    private final MQTTConnect server;

    @Autowired
    public MQTTListener(MQTTConnect server) {
    
    
        this.server = server;
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
    
    
        try {
    
    
            server.setMqttClient("admin", "password", new Callback());
            server.sub("/abcd-trace/#");
        } catch (MqttException e) {
    
    
            log.error(e.getMessage(), e);
        }
    }
}

This is just a description of the client, and if there is a chance, we will study the writing of publishers and agents later.

Guess you like

Origin blog.csdn.net/weixin_43487532/article/details/131827651