gatewayList = gatewayService.selectListByIsEnable(IsEnableConstant.IsEnableTrue);
+ for (GatewayDO gateway : gatewayList) {
+ if(StringUtils.isNotBlank(gateway.getTopic())){
+ SubscriptTopic topic = new SubscriptTopic(gateway.getTopic(),
+ gateway.getTopic(), Pattern.QUEUE, 0, dataHandler );
+ defaultBizTopicSet.getTopicMap().add(topic);
+ try {
+ client.subscribe(topic.getSubTopic(),0, dataHandler);
+ } catch (MqttException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ client.setCallback(new MqttCallbackImpl(defaultBizTopicSet.getTopicMap(),client,options));
+ log.info("共订阅: " + defaultBizTopicSet.getTopicMap().size() + " 个主题!");
+ }
+ else{
+ log.error("Mqtt is not connected !");
+ }
+
+ }
+
+ /**
+ * 需要订阅的topic 添加进client订阅
+ * */
+ @Override
+ public int subscribeTopic(String topic)throws MqttException{
+ SubscriptTopic subscriptTopic = new SubscriptTopic(topic, topic,Pattern.QUEUE, 0, dataHandler );
+ defaultBizTopicSet.getTopicMap().add(subscriptTopic);
+ client.subscribe(topic,0, dataHandler);
+ client.setCallback(new MqttCallbackImpl(defaultBizTopicSet.getTopicMap(),client,options));
+ return 0;
+ }
+ /**
+ * 关闭订阅topic 从client中关闭topic
+ * */
+ @Override
+ public int unsubscribeTopic(String topic)throws MqttException{
+ for (int i = 0; i < defaultBizTopicSet.getTopicMap().size(); i++) {
+ if(topic.equals(defaultBizTopicSet.getTopicMap().get(i).getSubTopic())){
+ defaultBizTopicSet.getTopicMap().remove(defaultBizTopicSet.getTopicMap().get(i));
+ break;
+ }
+ }
+ client.unsubscribe(topic);
+ client.setCallback(new MqttCallbackImpl(defaultBizTopicSet.getTopicMap(),client,options));
+ return 0;
+ }
+
+
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/Connect.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/Connect.java
new file mode 100644
index 0000000000..7eaa327d6e
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/Connect.java
@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.module.iot.framework.mqtt.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+
+/**
+ * 设备上线
+ * 邮箱:275236367@qq.com
+ * 创建时间: 2020/1/4
+ * @author jie
+ */
+@Data
+@ToString
+@NoArgsConstructor
+@AllArgsConstructor
+public class Connect {
+ /**
+ * 客户端id
+ */
+ private String clientid;
+ /**
+ * 用户名
+ */
+ private String username;
+ /**
+ * ip地址
+ */
+ private String ipaddress;
+ /**
+ *连接回执
+ */
+ private int connack;
+ /**
+ * 事件触发时间 (ms)
+ */
+ private long ts;
+ /**
+ * 协议版本
+ */
+ private int proto_ver;
+ /**
+ * 协议名字
+ */
+ private String proto_name;
+ /**
+ * MQTT clean_start
+ */
+ private boolean clean_start;
+ /**
+ *保持连接
+ */
+ private int keepalive;
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/Disconnect.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/Disconnect.java
new file mode 100644
index 0000000000..1165a2906f
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/Disconnect.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.iot.framework.mqtt.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+
+/**
+ *
设备下线
+ * @author jie
+ */
+@Data
+@ToString
+@NoArgsConstructor
+@AllArgsConstructor
+public class Disconnect {
+ /**
+ * 客户端id
+ */
+ private String clientid;
+ /**
+ * 用户名
+ */
+ private String username;
+ /**
+ * 终端连接断开原因
+ */
+ private String reason;
+ /**
+ * 事件触发时间 (ms)
+ */
+ private long ts;
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/IoData.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/IoData.java
new file mode 100644
index 0000000000..9eeee356c9
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/IoData.java
@@ -0,0 +1,13 @@
+package cn.iocoder.yudao.module.iot.framework.mqtt.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class IoData {
+ String u;
+ String v;
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/MqttData.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/MqttData.java
new file mode 100644
index 0000000000..fd6ca73454
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/MqttData.java
@@ -0,0 +1,19 @@
+package cn.iocoder.yudao.module.iot.framework.mqtt.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Map;
+
+// 同一的数据格式
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class MqttData {
+ protected String deviceID;
+ protected String gatewayID;
+ protected Map deviceData;
+ protected String deviceDataTime;
+
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/Pattern.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/Pattern.java
new file mode 100644
index 0000000000..51302e5df1
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/Pattern.java
@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.iot.framework.mqtt.entity;
+
+/**
+ * 订阅模式
+ * @author jie
+ */
+
+public enum Pattern {
+ /**
+ * 普通订阅
+ */
+ NONE,
+ /**
+ * 不带群组的共享订阅
+ */
+ QUEUE,
+ /**
+ * 带群组的共享订阅
+ */
+ SHARE;
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/SubscriptTopic.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/SubscriptTopic.java
new file mode 100644
index 0000000000..4a55c8bbd4
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/entity/SubscriptTopic.java
@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.iot.framework.mqtt.entity;
+
+import lombok.*;
+import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
+
+/**
+ * @author jie
+ */
+@Data
+@Builder
+@ToString
+@NoArgsConstructor
+@AllArgsConstructor
+public class SubscriptTopic {
+ /**
+ * 原主题
+ */
+ private String topic;
+ /**
+ * 订阅主题
+ */
+ private String subTopic;
+ /**
+ * 订阅模式
+ */
+ private Pattern pattern;
+ /**
+ * 消息等级
+ */
+ private int qos;
+ /**
+ * 消费类
+ */
+ private IMqttMessageListener messageListener;
+
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/utils/ApplicationContextUtil.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/utils/ApplicationContextUtil.java
new file mode 100644
index 0000000000..ee245b02db
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/utils/ApplicationContextUtil.java
@@ -0,0 +1,48 @@
+package cn.iocoder.yudao.module.iot.framework.mqtt.utils;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+
+/**
+ * 类名称:ApplicationContextUtil
+ * 类描述:
+ *
+ *
从容器中获取bean
+ */
+@Component
+public class ApplicationContextUtil {
+
+ private static ApplicationContextUtil instance;
+ @Autowired
+ private ApplicationContext applicationContext;
+
+ @PostConstruct
+ public void applicationContextUtil() {
+ instance = this;
+ }
+
+ /**
+ * 根据字节码获取bean
+ * @param clazz
+ * @param
+ * @return
+ */
+ public static T getBean(Class clazz) {
+ return instance.applicationContext.getBean(clazz);
+ }
+
+ /**
+ * 根据名字获取bean
+ * @param name
+ * @param
+ * @return
+ * @throws BeansException
+ */
+ public static T getBean(String name) throws BeansException {
+ return (T) instance.applicationContext.getBean(name);
+ }
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/utils/DateUtils.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/utils/DateUtils.java
new file mode 100644
index 0000000000..1981d0fd5e
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/utils/DateUtils.java
@@ -0,0 +1,304 @@
+package cn.iocoder.yudao.module.iot.framework.mqtt.utils;
+
+import org.apache.commons.lang3.time.DateFormatUtils;
+
+import java.lang.management.ManagementFactory;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+public class DateUtils extends org.apache.commons.lang3.time.DateUtils{
+ /**
+ * 将本地时间, 转换成目标时区的时间
+ * @param sourceDate
+ * @return
+ */
+ public static Date convertTimezone(Date sourceDate, String targetZoneId){
+ return convertTimezone(sourceDate, TimeZone.getTimeZone(targetZoneId));
+ }
+
+ public static Date convertTimezone(Date sourceDate, String sourceZoneId, String targetZoneId){
+ TimeZone sourceTimeZone=TimeZone.getTimeZone(sourceZoneId);
+ TimeZone targetTimeZone=TimeZone.getTimeZone(targetZoneId);
+
+ return convertTimezone(sourceDate, sourceTimeZone, targetTimeZone);
+ }
+
+ /**
+ * 将本地时间,转换成对应时区的时间
+ * @param localDate
+ * @param targetTimezone 转换成目标时区所在的时间
+ * @return
+ */
+ public static Date convertTimezone(Date localDate, TimeZone targetTimezone){
+ return convertTimezone(localDate, TimeZone.getDefault(), targetTimezone);
+ }
+
+
+ /**
+ * 将sourceDate转换成指定时区的时间
+ * @param sourceDate
+ * @param sourceTimezone sourceDate所在的时区
+ * @param targetTimezone 转化成目标时间所在的时区
+ * @return
+ */
+ public static Date convertTimezone(Date sourceDate, TimeZone sourceTimezone, TimeZone targetTimezone){
+
+
+ // targetDate - sourceDate=targetTimezone-sourceTimezone
+ // --->
+ // targetDate=sourceDate + (targetTimezone-sourceTimezone)
+
+
+ Calendar calendar=Calendar.getInstance();
+ // date.getTime() 为时间戳, 为格林尼治到系统现在的时间差,世界各个地方获取的时间戳是一样的,
+ // 格式化输出时,因为设置了不同的时区,所以输出不一样
+ long sourceTime=sourceDate.getTime();
+
+
+ calendar.setTimeZone(sourceTimezone);
+ calendar.setTimeInMillis(sourceTime);// 设置之后,calendar会计算各种filed对应的值,并保存
+
+ //获取源时区的到UTC的时区差
+ int sourceZoneOffset=calendar.get(Calendar.ZONE_OFFSET);
+
+
+ calendar.setTimeZone(targetTimezone);
+ calendar.setTimeInMillis(sourceTime);
+
+ int targetZoneOffset=calendar.get(Calendar.ZONE_OFFSET);
+ int targetDaylightOffset=calendar.get(Calendar.DST_OFFSET); // 夏令时
+
+
+ long targetTime=sourceTime+ (targetZoneOffset+targetDaylightOffset) -sourceZoneOffset;
+
+ return new Date(targetTime);
+
+ }
+
+ public static String addDateMinut(String day, int hour){
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ Date date = null;
+ try {
+ date = format.parse(day);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ if (date == null)
+ return "";
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+ cal.add(Calendar.HOUR, -hour);// 24小时制
+ date = cal.getTime();
+ cal = null;
+ return format.format(date);
+ }
+
+ public static String addDateDay(String time, int day){
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ Date date = null;
+ try {
+ date = format.parse(time);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ if (date == null)
+ return "";
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+ cal.add(Calendar.DAY_OF_MONTH, -day);// 日
+ date = cal.getTime();
+ cal = null;
+ return format.format(date);
+ }
+
+
+ public static String addDateMonth(String day, int hour){
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ Date date = null;
+ try {
+ date = format.parse(day);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ if (date == null)
+ return "";
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+ cal.add(Calendar.MONTH, hour);// 月
+ date = cal.getTime();
+ cal = null;
+ return format.format(date);
+ }
+ public static String YYYY = "yyyy";
+
+ public static String YYYY_MM = "yyyy-MM";
+
+ public static String YYYY_MM_DD = "yyyy-MM-dd";
+
+ public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
+
+ public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+ public static String YYYY_MM_DD_HH_MM_SS_SSS = "yyyy-MM-dd HH:mm:ss.SSS";
+ private static String[] parsePatterns = {
+ "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
+ "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
+ "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
+
+ /**
+ * 获取当前Date型日期
+ *
+ * @return Date() 当前日期
+ */
+ public static Date getNowDate()
+ {
+ return new Date();
+ }
+
+ /**
+ * 获取当前日期, 默认格式为yyyy-MM-dd
+ *
+ * @return String
+ */
+ public static String getDate()
+ {
+ return dateTimeNow(YYYY_MM_DD);
+ }
+ public static String getMills()
+ {
+ return dateTimeNow(YYYY_MM_DD_HH_MM_SS_SSS);
+ }
+ public static String getMills(Date date)
+ {
+ return parseDateToStr(YYYY_MM_DD_HH_MM_SS_SSS, date);
+ }
+ public static Long getMillsLong()
+ {
+ return new Date().getTime();
+ }
+ public static Long getMillsLong(Date date)
+ {
+ return date.getTime();
+ }
+ public static final String getTime()
+ {
+ return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
+ }
+
+ public static final String dateTimeNow()
+ {
+ return dateTimeNow(YYYYMMDDHHMMSS);
+ }
+
+ public static final String dateTimeNow(final String format)
+ {
+ return parseDateToStr(format, new Date());
+ }
+
+ public static final String dateTime(final Date date)
+ {
+ return parseDateToStr(YYYY_MM_DD, date);
+ }
+
+ public static final String parseDateToStr(final String format, final Date date)
+ {
+ return new SimpleDateFormat(format).format(date);
+ }
+
+ public static final Date dateTime(final String format, final String ts)
+ {
+ try
+ {
+ return new SimpleDateFormat(format).parse(ts);
+ }
+ catch (ParseException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * 日期路径 即年/月/日 如2018/08/08
+ */
+ public static final String datePath()
+ {
+ Date now = new Date();
+ return DateFormatUtils.format(now, "yyyy/MM/dd");
+ }
+
+ /**
+ * 日期路径 即年/月/日 如20180808
+ */
+ public static final String dateTime()
+ {
+ Date now = new Date();
+ return DateFormatUtils.format(now, "yyyyMMdd");
+ }
+
+ /**
+ * 日期型字符串转化为日期 格式
+ */
+ public static Date parseDate(Object str)
+ {
+ if (str == null)
+ {
+ return null;
+ }
+ try
+ {
+ return parseDate(str.toString(), parsePatterns);
+ }
+ catch (ParseException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * 获取服务器启动时间
+ */
+ public static Date getServerStartDate()
+ {
+ long time = ManagementFactory.getRuntimeMXBean().getStartTime();
+ return new Date(time);
+ }
+
+ /**
+ * 计算两个时间差
+ */
+ public static String getDatePoor(Date endDate, Date nowDate)
+ {
+ long nd = 1000 * 24 * 60 * 60;
+ long nh = 1000 * 60 * 60;
+ long nm = 1000 * 60;
+ // long ns = 1000;
+ // 获得两个时间的毫秒时间差异
+ long diff = endDate.getTime() - nowDate.getTime();
+ // 计算差多少天
+ long day = diff / nd;
+ // 计算差多少小时
+ long hour = diff % nd / nh;
+ // 计算差多少分钟
+ long min = diff % nd % nh / nm;
+ // 计算差多少秒//输出结果
+ // long sec = diff % nd % nh % nm / ns;
+ return day + "天" + hour + "小时" + min + "分钟";
+ }
+
+ public static Long strToTimeStamp(String dateTime,String format) throws ParseException {
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
+ return simpleDateFormat.parse(dateTime).getTime();
+ }
+ public static LocalDateTime strToLocalDateTime(String dateTimeString) throws ParseException {
+ // 定义日期时间格式
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
+ // 使用DateTimeFormatter解析字符串为LocalDateTime
+ LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, formatter);
+ return dateTime;
+ }
+
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/utils/MqttDataUtils.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/utils/MqttDataUtils.java
new file mode 100644
index 0000000000..d17d20a365
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/utils/MqttDataUtils.java
@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.iot.framework.mqtt.utils;
+
+import cn.iocoder.yudao.module.iot.framework.mqtt.entity.MqttData;
+import com.alibaba.fastjson.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+
+@Slf4j
+public class MqttDataUtils {
+
+ public static MqttData parse(String entity){
+ try {
+ MqttData data = JSON.parseObject(entity, MqttData.class);
+ return data;
+ }catch (Exception e){
+ e.printStackTrace();
+ log.error("MqttDataHandler.JSON.parseObject error:");
+ }
+ return null;
+ }
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/utils/PubMessageUtils.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/utils/PubMessageUtils.java
new file mode 100644
index 0000000000..9556777600
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/utils/PubMessageUtils.java
@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.iot.framework.mqtt.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.eclipse.paho.client.mqttv3.MqttClient;
+import org.eclipse.paho.client.mqttv3.MqttException;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * 发布消息工具类
+ * 注意,直接注入client pub会报错 报错原因我也不知道 如果有大佬知道就请留言告知一下
+ * @author jie
+ */
+@Slf4j
+public class PubMessageUtils {
+
+ public static boolean pub(String topic, String message) throws MqttException, UnsupportedEncodingException {
+ return pub(topic, message.getBytes(StandardCharsets.UTF_8), 0, false);
+ }
+
+ public static boolean pub(String topic, String message, int qos) throws MqttException, UnsupportedEncodingException {
+ return pub(topic, message.getBytes(StandardCharsets.UTF_8), qos, false);
+ }
+
+ public static boolean pub(String topic, byte[] message) throws MqttException {
+ return pub(topic, message, 0, false);
+ }
+
+ public static boolean pub(String topic, byte[] message, int qos) throws MqttException {
+ return pub(topic, message, qos, false);
+ }
+
+ public static boolean pub(String topic, byte[] message, int qos, boolean retained) throws MqttException {
+ try {
+ MqttClient client = ApplicationContextUtil.getBean(MqttClient.class);
+ client.publish(topic, message, qos, retained);
+ } catch (MqttException e) {
+ log.error(e.toString());
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/utils/ThreadUtils.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/utils/ThreadUtils.java
new file mode 100644
index 0000000000..39fe9daa77
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/mqtt/utils/ThreadUtils.java
@@ -0,0 +1,14 @@
+package cn.iocoder.yudao.module.iot.framework.mqtt.utils;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * @author jie
+ */
+public class ThreadUtils {
+ /**
+ * 线程池
+ */
+ public static ExecutorService executorService = Executors.newFixedThreadPool(50);
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/redis/RedisKeyConstants.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/redis/RedisKeyConstants.java
new file mode 100644
index 0000000000..393ee60072
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/redis/RedisKeyConstants.java
@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.module.iot.framework.redis;
+
+/**
+ * CRM Redis Key 枚举类
+ *
+ * @author 芋道源码
+ */
+public interface RedisKeyConstants {
+
+ /**
+ * 序号的缓存
+ *
+ * KEY 格式:trade_no:{prefix}
+ * VALUE 数据格式:编号自增
+ */
+ String NO = "crm:seq_no:";
+
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayService.java
index 6cc34110ce..4e44a169c4 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayService.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayService.java
@@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.gateway.GatewayDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import java.util.List;
+
/**
* 网关 Service 接口
*
@@ -44,6 +46,7 @@ public interface GatewayService {
*/
GatewayDO getGateway(Long id);
+ List selectListByIsEnable(boolean isEnable);
/**
* 获得网关分页
*
@@ -93,4 +96,5 @@ public interface GatewayService {
*/
DeviceDO getDevice(Long id);
+
}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayServiceImpl.java
index 25ec07302f..e631d64299 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayServiceImpl.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayServiceImpl.java
@@ -2,6 +2,12 @@ package cn.iocoder.yudao.module.iot.service.gateway;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
import cn.iocoder.yudao.module.iot.dal.mysql.device.DeviceMapper;
+import cn.iocoder.yudao.module.iot.framework.constant.Constants;
+import cn.iocoder.yudao.module.iot.framework.constant.IsEnableConstant;
+import cn.iocoder.yudao.module.iot.framework.mqtt.consumer.IMqttservice;
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.paho.client.mqttv3.MqttException;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
@@ -15,6 +21,8 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.iot.dal.mysql.gateway.GatewayMapper;
+import java.util.List;
+
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
@@ -32,6 +40,7 @@ public class GatewayServiceImpl implements GatewayService {
@Resource
private DeviceMapper deviceMapper;
+
@Override
public Long createGateway(GatewaySaveReqVO createReqVO) {
// 插入
@@ -73,6 +82,10 @@ public class GatewayServiceImpl implements GatewayService {
return gatewayMapper.selectById(id);
}
+ @Override
+ public List selectListByIsEnable(boolean isEnable){
+ return gatewayMapper.selectListByIsEnable(isEnable);
+ }
@Override
public PageResult getGatewayPage(GatewayPageReqVO pageReqVO) {
return gatewayMapper.selectPage(pageReqVO);
diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml
index fe592406c8..017537bb94 100644
--- a/yudao-server/src/main/resources/application.yaml
+++ b/yudao-server/src/main/resources/application.yaml
@@ -236,6 +236,8 @@ yudao:
- rep_demo_jianpiao
- tmp_report_data_1
- tmp_report_data_income
+ - iot_gateway
+ - iot_mqtt_record
sms-code: # 短信验证码相关的配置项
expire-times: 10m
send-frequency: 1m
@@ -262,4 +264,15 @@ debug: false
# 积木报表配置
jeecg:
jmreport:
- saas-mode: tenant
\ No newline at end of file
+ saas-mode: tenant
+
+#tcp://47.112.167.85:1883 tcp://47.106.185.127:1883
+emqx:
+ broker: tcp://47.106.185.127:1883 #broker地址47.112.167.85
+ clientId: emqx-9521
+ userName: admin #授权账号 一定要授权的
+ password: public123 #密码
+ cleanSession: true #是否清除会话
+ reconnect: true #是否断线重连
+ timeout: 20 #连接超时时间
+ keepAlive: 10 #心跳间隔
\ No newline at end of file