package com.ruoyi.components.mqtt;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.generate.domain.DeviceCommunicationRecord;
import com.ruoyi.generate.mapper.DeviceCommunicationRecordMapper;
import com.ruoyi.tools.upload.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.Objects;
/**
* @author cyl
* @time 2023/4/24
*/
@Component
@Slf4j
public class MqttClientUtil {
@Value("${spring.mqtt.username}")
private String username;
@Value("${spring.mqtt.password}")
private String password;
@Value("${spring.mqtt.url}")
private String host;
@Value("${spring.mqtt.default-topic}")
private String topic;
@Value("${spring.mqtt.client-id}")
private String clientId;
@Value("${spring.mqtt.timeout}")
private int timeout;
@Value("${spring.mqtt.keepalive}")
private int interval;
@Value("${spring.mqtt.auto-connect}")
private boolean autoConnect;
private MqttClient mqttClient;
private MqttConnectOptions mqttConnectOptions;
@Autowired
private DeviceCommunicationRecordMapper deviceCommunicationRecordMapper;
@PostConstruct
private void init() {
System.out.println("" +
"MQTT服务启动成功" +
" \n" +
",--. ,--. ,-----. ,--------. ,--------. \n" +
"| `.' | ' .-. ' '--. .--' '--. .--' \n" +
"| |'.'| | | | | | | | | | \n" +
"| | | | ' '-' '-. | | | | \n" +
"`--' `--' `-----'--' `--' `--' \n" +
" ");
connect(host, clientId);
}
/**
* 连接mqtt
*
* @param host
* @param clientId
*/
public void connect(String host, String clientId) {
try {
mqttClient = new MqttClient(host, clientId, new MemoryPersistence());
mqttConnectOptions = getMqttConnectOptions();
mqttClient.connect(mqttConnectOptions);
} catch (Exception e) {
System.out.println("mqtt服务连接异常!");
e.printStackTrace();
}
}
/**
* 设置连接对象信息
* setCleanSession true 断开连接即清楚会话 false 保留连接信息 离线还会继续发消息
*
* @return
*/
private MqttConnectOptions getMqttConnectOptions() {
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setUserName(username);
mqttConnectOptions.setPassword(password.toCharArray());
mqttConnectOptions.setServerURIs(new String[]{host});
mqttConnectOptions.setKeepAliveInterval(interval);
mqttConnectOptions.setConnectionTimeout(timeout);
mqttConnectOptions.setCleanSession(true);
mqttConnectOptions.setAutomaticReconnect(autoConnect);
return mqttConnectOptions;
}
/**
* mqtt连接状态
*
* @return
*/
private boolean isConnect() {
if (Objects.isNull(this.mqttClient)) {
return false;
}
return mqttClient.isConnected();
}
/**
* 设置重连
*
* @throws Exception
*/
private void reConnect() throws Exception {
if (Objects.nonNull(this.mqttClient)) {
System.out.println("mqtt 服务已重新连接...");
this.mqttClient.connect(this.mqttConnectOptions);
}
}
/**
* 断开连接
*
* @throws Exception
*/
public void closeConnect() throws Exception {
if (Objects.nonNull(this.mqttClient)) {
System.out.println("mqtt 服务已断开连接...");
this.mqttClient.disconnect();
}
}
/**
* 发布消息
*
* @param topic
* @param message
* @param qos
* @throws Exception
*/
public void sendMessage(String topic, String message, int qos) throws Exception {
if (Objects.nonNull(this.mqttClient) && this.mqttClient.isConnected()) {
MqttMessage mqttMessage = new MqttMessage();
mqttMessage.setPayload(message.getBytes());
mqttMessage.setQos(qos);
MqttTopic mqttTopic = mqttClient.getTopic(topic);
if (Objects.nonNull(mqttTopic)) {
try {
MqttDeliveryToken publish = mqttTopic.publish(mqttMessage);
if (publish.isComplete()) {
// log.info("消息发送成功---->{}", message);
//TODO 发送的数据需要存储
DeviceCommunicationRecord deviceCommunicationRecord=new DeviceCommunicationRecord();
deviceCommunicationRecord.setTopic(topic);
deviceCommunicationRecord.setContent(message);
deviceCommunicationRecord.setCreateBy(SecurityUtils.getUserId().toString());
deviceCommunicationRecord.setCreateTime(DateUtils.getNowDate());
//插入发送实体表
deviceCommunicationRecordMapper.insertDeviceCommunicationRecord(deviceCommunicationRecord);
System.out.println("主题:"+mqttTopic+"的消息发送成功!\n"+"载荷为"+message);
}
} catch (Exception e) {
System.out.println("消息发送异常!");
e.printStackTrace();
}
}
} else {
reConnect();
}
}
/**
* 订阅消息
*
* @param topic
* @param qos
* @throws Exception
*/
public void subscribe(String topic, int qos) throws Exception {
if (Objects.nonNull(this.mqttClient) && this.mqttClient.isConnected()) {
mqttClient.setCallback(new MqttCallback() {
//连接丢失处理
@Override
public void connectionLost(Throwable cause) {
System.out.println("连接已丢失");
cause.printStackTrace();
try {
//丢失重连
mqttClient.reconnect();
} catch (MqttException e) {
e.printStackTrace();
}
}
//消息处理
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
String payload = new String(message.getPayload());
System.out.println("收到的消息的主题为:" +topic);
System.out.println("收到的消息的载荷为:" + payload);
//TODO 收到的消息需要储存到数据库中
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
System.out.println("消息发送已完成");
}
});
mqttClient.subscribe(topic, qos);
} else {
reConnect();
}
}
}
引入的依赖
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.5</version>
</dependency>