add mqtt record

plp
chenshuichuan 2 years ago
parent 2543dd5922
commit 57d7761e72

@ -14,8 +14,7 @@
<name>${project.artifactId}</name>
<description>
report 模块,主要实现数据可视化报表等功能:
1. 基于「积木报表」实现,打印设计、报表设计、图形设计、大屏设计等。
iot 模块,主要实现数据
</description>
<dependencies>
<dependency>
@ -58,12 +57,6 @@
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-test</artifactId>
</dependency>
<!-- 积木报表-->
<dependency>
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimureport-spring-boot-starter</artifactId>
</dependency>
<!-- 单独依赖升级版本解决低版本validator失败问题 -->
<dependency>
<groupId>xerces</groupId>
@ -74,6 +67,16 @@
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-redis</artifactId>
</dependency>
</dependencies>
</project>

@ -1,6 +1,10 @@
package cn.iocoder.yudao.module.iot.controller.admin.gateway;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
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.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
@ -37,19 +41,56 @@ public class GatewayController {
@Resource
private GatewayService gatewayService;
@Resource
private IMqttservice mqttservice;
@PostMapping("/create")
@Operation(summary = "创建网关")
@PreAuthorize("@ss.hasPermission('iot:gateway:create')")
public CommonResult<Long> createGateway(@Valid @RequestBody GatewaySaveReqVO createReqVO) {
return success(gatewayService.createGateway(createReqVO));
Long id = gatewayService.createGateway(createReqVO);
if (id != null && IsEnableConstant.IsEnableTrue == createReqVO.getIsEnable()
&& StringUtils.isNotBlank(createReqVO.getTopic())) {
try {
mqttservice.subscribeTopic(createReqVO.getTopic());
} catch (MqttException e) {
e.printStackTrace();
}
}
return success(id);
}
@PutMapping("/update")
@Operation(summary = "更新网关")
@PreAuthorize("@ss.hasPermission('iot:gateway:update')")
public CommonResult<Boolean> updateGateway(@Valid @RequestBody GatewaySaveReqVO updateReqVO) {
GatewayDO old = gatewayService.getGateway(updateReqVO.getId());
gatewayService.updateGateway(updateReqVO);
/**todo 订阅*/
try {
if (old != null && StringUtils.isNotBlank(old.getTopic()) && StringUtils.isNotBlank(updateReqVO.getTopic())) {
boolean sameTopic = false;
if (old.getTopic().equals(updateReqVO.getTopic())) sameTopic = true;
if (sameTopic) {
//启用订阅
if (updateReqVO.getIsEnable().equals(IsEnableConstant.IsEnableTrue))
mqttservice.subscribeTopic(updateReqVO.getTopic());
//禁用订阅
else mqttservice.unsubscribeTopic(updateReqVO.getTopic());
} else {
//禁用旧订阅
if (old.getIsEnable().equals(IsEnableConstant.IsEnableTrue))
mqttservice.unsubscribeTopic(old.getTopic());
//启用新订阅
if (updateReqVO.getIsEnable().equals(IsEnableConstant.IsEnableTrue))
mqttservice.subscribeTopic(updateReqVO.getTopic());
}
}
} catch (MqttException e) {
e.printStackTrace();
}
return success(true);
}

@ -21,6 +21,8 @@ public class MqttRecordPageReqVO extends PageParam {
@Schema(description = "采集时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] deviceDataTime;
@Schema(description = "采集时间sss")
private Long[] deviceDataTimeLong;
@Schema(description = "数据")
private String deviceData;

@ -24,6 +24,9 @@ public class MqttRecordRespVO {
@Schema(description = "采集时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("采集时间")
private LocalDateTime deviceDataTime;
@Schema(description = "采集时间sss")
@ExcelProperty("采集时间sss")
private Long deviceDataTimeLong;
@Schema(description = "数据")
@ExcelProperty("数据")

@ -23,6 +23,8 @@ public class MqttRecordSaveReqVO {
@Schema(description = "采集时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "采集时间不能为空")
private LocalDateTime deviceDataTime;
@Schema(description = "采集时间sss")
private Long deviceDataTimeLong;
@Schema(description = "数据")
private String deviceData;

@ -40,6 +40,10 @@ public class MqttRecordDO extends BaseDO {
*
*/
private LocalDateTime deviceDataTime;
/**
*
*/
private Long deviceDataTimeLong;
/**
*
*/

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.dal.mysql.gateway;
import java.util.*;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
@ -31,5 +32,8 @@ public interface GatewayMapper extends BaseMapperX<GatewayDO> {
.eqIfPresent(GatewayDO::getTopic, reqVO.getTopic())
.orderByDesc(GatewayDO::getId));
}
default List<GatewayDO> selectListByIsEnable(boolean isEnable) {
return selectList(GatewayDO::getIsEnable, isEnable);
}
}

@ -21,6 +21,7 @@ public interface MqttRecordMapper extends BaseMapperX<MqttRecordDO> {
return selectPage(reqVO, new LambdaQueryWrapperX<MqttRecordDO>()
.likeIfPresent(MqttRecordDO::getMachineName, reqVO.getMachineName())
.betweenIfPresent(MqttRecordDO::getDeviceDataTime, reqVO.getDeviceDataTime())
.betweenIfPresent(MqttRecordDO::getDeviceDataTimeLong, reqVO.getDeviceDataTimeLong())
.eqIfPresent(MqttRecordDO::getDeviceData, reqVO.getDeviceData())
.eqIfPresent(MqttRecordDO::getDeviceCode, reqVO.getDeviceCode())
.likeIfPresent(MqttRecordDO::getDeviceName, reqVO.getDeviceName())

@ -0,0 +1,6 @@
package cn.iocoder.yudao.module.iot.framework.constant;
public class Constants {
public final static String MQTT_timestamp_format = "yyyy-MM-dd HH:mm:ss.SSS";
}

@ -0,0 +1,12 @@
package cn.iocoder.yudao.module.iot.framework.constant;
public class IsEnableConstant {
/**
*
*/
public final static boolean IsEnableFalse = false;
/**
*
*/
public final static boolean IsEnableTrue = true;
}

@ -0,0 +1,41 @@
package cn.iocoder.yudao.module.iot.framework.mqtt.annotation;
import cn.iocoder.yudao.module.iot.framework.mqtt.entity.Pattern;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
/**
*
* @author jie
*/
@Component
@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Topic {
/**
* topic
* @return
*/
String topic() default "";
/**
* qos
* @return
*/
int qos() default 0;
/**
*
* @return
*/
Pattern patten() default Pattern.NONE;
/**
*
* @return
*/
String group() default "group1";
}

@ -0,0 +1,103 @@
package cn.iocoder.yudao.module.iot.framework.mqtt.common;
import cn.iocoder.yudao.module.iot.framework.mqtt.entity.Pattern;
import cn.iocoder.yudao.module.iot.framework.mqtt.entity.SubscriptTopic;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
import java.util.List;
/**
* mqtt
*
* @author jie
*/
@Data
@Slf4j
public class MqttCallbackImpl implements MqttCallbackExtended {
private final List<SubscriptTopic> topicMap;
private final MqttClient client;
private final MqttConnectOptions option;
/**
*
*
* @param throwable
*/
@SneakyThrows
@Override
public void connectionLost(Throwable throwable) {
while (!client.isConnected()) {
log.info("emqx 重新连接");
client.connect(option);
Thread.sleep(6000);
}
log.info("emqx 重接成功");
}
/**
*
*
* @param topic
* @param message
*/
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
for (SubscriptTopic subscriptTopic : topicMap) {
if (subscriptTopic.getPattern() != Pattern.NONE && isMatched(subscriptTopic.getTopic(), topic)) {
log.info("MqttCallbackImpl,messageArrived:topic="+topic+",message="+message);
subscriptTopic.getMessageListener().messageArrived(topic, message);
break;
}
}
}
/**
*
*
* @param topicFilter
* @param topic
* @return
*/
private boolean isMatched(String topicFilter, String topic) {
return MqttTopic.isMatched(topicFilter, topic);
}
/**
*
*
* @param token token
*/
@SneakyThrows
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
String[] topics = token.getTopics();
for (String topic : topics) {
log.info("向主题:" + topic + "发送数据:" + new String(token.getMessage().getPayload()));
}
}
/**
* emq
*
* @param b
* @param s
*/
@Override
public void connectComplete(boolean b, String s) {
if (client.isConnected()) {
for (SubscriptTopic sub : topicMap) {
try {
client.subscribe(sub.getSubTopic(), sub.getQos(), sub.getMessageListener());
log.info("订阅主题:" + sub.getSubTopic() + " Listener:" + sub.getMessageListener());
} catch (MqttException e) {
//log.info("订阅主题失败:" + sub.getSubTopic());
e.printStackTrace();
}
}
log.info("共订阅: " + topicMap.size() + " 个主题!");
}
}
}

@ -0,0 +1,16 @@
package cn.iocoder.yudao.module.iot.framework.mqtt.common;
import org.eclipse.paho.client.mqttv3.MqttMessage;
/**
* @author jie
*/
public interface MsgDecoder<T> {
/**
*
* @param msg
* @return
*/
T decoder(MqttMessage msg);
}

@ -0,0 +1,13 @@
package cn.iocoder.yudao.module.iot.framework.mqtt.common;
/**
* @author jie
*/
public interface MsgEncoder<T> {
/**
* string
* @param t
* @return
*/
String encoder(T t);
}

@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.iot.framework.mqtt.common;
import cn.iocoder.yudao.module.iot.framework.mqtt.utils.ThreadUtils;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
import org.eclipse.paho.client.mqttv3.MqttMessage;
/**
*
*
* @author jie
*/
@Slf4j
public abstract class SuperConsumer<T> implements IMqttMessageListener, MsgDecoder<T> {
@Override
public void messageArrived(String topic, MqttMessage mqttMessage) {
// log.info("收到主题 : " + topic + " 的消息: " + new String(mqttMessage.getPayload()));
ThreadUtils.executorService.submit(() -> {
try {
T decoder = decoder(mqttMessage);
msgHandler(topic, decoder);
} catch (Exception ex) {
//解决业务处理错误导致断线问题
log.error(topic+":解决业务处理错误导致断线问题");
log.error(ex.toString());
}
});
}
/**
*
*
* @param topic
* @param entity
*/
protected abstract void msgHandler(String topic, T entity);
}

@ -0,0 +1,17 @@
package cn.iocoder.yudao.module.iot.framework.mqtt.config;
import cn.iocoder.yudao.module.iot.framework.mqtt.entity.SubscriptTopic;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
// 默认的业务主题集合,使用注解,收集所有的业务处理相关类实例
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DefaultBizTopicSet {
List<SubscriptTopic> topicMap = new ArrayList<>();
}

@ -0,0 +1,96 @@
package cn.iocoder.yudao.module.iot.framework.mqtt.config;
import cn.iocoder.yudao.module.iot.framework.mqtt.annotation.Topic;
import cn.iocoder.yudao.module.iot.framework.mqtt.common.MqttCallbackImpl;
import cn.iocoder.yudao.module.iot.framework.mqtt.entity.Pattern;
import cn.iocoder.yudao.module.iot.framework.mqtt.entity.SubscriptTopic;
import cn.iocoder.yudao.module.iot.framework.mqtt.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* mqtt
*
* @author jie
*/
@Slf4j
@Configuration
@EnableConfigurationProperties(DefaultEmqProperties.class)
public class DefaultEmqConfig {
/**
* MQTT
*
* @param emqProperties
* @return
*/
@Bean
public MqttConnectOptions getOption(DefaultEmqProperties emqProperties) {
MqttConnectOptions options = new MqttConnectOptions();
emqProperties.setClientId("clientId"+String.valueOf(DateUtils.getMillsLong()));
log.info("------mqtt clientid ="+ emqProperties.getClientId());
options.setUserName(emqProperties.getUserName());
options.setPassword(emqProperties.getPassword().toCharArray());
// 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录这里设置为true表示每次连接到服务器都以新的身份连接
options.setCleanSession(emqProperties.getCleanSession());
//断线重连
options.setAutomaticReconnect(emqProperties.getReconnect());
// 设置超时时间 单位为秒
options.setConnectionTimeout(emqProperties.getTimeout());
// 设置会话心跳时间 单位为秒 服务器会每隔1.5*10秒的时间向客户端发送个消息判断客户端是否在线但这个方法并没有重连的机制
options.setKeepAliveInterval(emqProperties.getKeepAlive());
return options;
}
@Bean
public DefaultBizTopicSet defaultBizTopicSet(ApplicationContext applicationContext){
List<SubscriptTopic> topicMap = new ArrayList<>();
//得到所有使用@Topic注解的类
Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(Topic.class);
for (String className : beansWithAnnotation.keySet()) {
Class<?> classByteCode = beansWithAnnotation.get(className).getClass();
//获取类的注解属性
Topic annotation = AnnotationUtils.findAnnotation(classByteCode, Topic.class);
String topic = annotation.topic();
int qos = annotation.qos();
Pattern patten = annotation.patten();
String group = annotation.group();
String subTopic = topic;
if (patten == Pattern.SHARE) {
subTopic = group + "/" + topic;
} else if (patten == Pattern.QUEUE) {
subTopic = topic;
}
topicMap.add(new SubscriptTopic(topic, subTopic, patten, qos, (IMqttMessageListener) applicationContext.getBean(classByteCode)));
}
return new DefaultBizTopicSet(topicMap);
}
/**
* MQTT
*
* @param options MQTT
* @param emqProperties MQTT
* @param applicationContext
* @return
* @throws Exception
*/
@Bean
public MqttClient mqttClient(MqttConnectOptions options, DefaultEmqProperties emqProperties, DefaultBizTopicSet defaultBizTopicSet, ApplicationContext applicationContext) throws Exception {
MqttClient mqttClient = new MqttClient(emqProperties.getBroker(), emqProperties.getClientId(), new MemoryPersistence());
mqttClient.setCallback(new MqttCallbackImpl(defaultBizTopicSet.getTopicMap(), mqttClient, options));
return mqttClient;
}
}

@ -0,0 +1,47 @@
package cn.iocoder.yudao.module.iot.framework.mqtt.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
*
* @author jie
*/
@Data
@ConfigurationProperties(prefix = "emqx")
public class DefaultEmqProperties {
//public static final String PREFIX = "emqx";
/**
* emq
*/
private String broker;
/**
* emq client id
*/
private String clientId;
/**
*
*/
private String userName;
/**
*
*/
private String password;
/**
* session,falsetrue
*/
private Boolean cleanSession;
/**
* 线
*/
private Boolean reconnect;
/**
*
*/
private Integer timeout;
/**
*
*/
private Integer keepAlive;
}

@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.iot.framework.mqtt.config;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
@Slf4j
public class DefaultMqttStarter implements ApplicationListener<ApplicationReadyEvent> {
@Resource
private MqttConnectOptions options;
@Resource
private MqttClient mqttClient;
@SneakyThrows
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
// catch异常不然连不上emqx项目就跑不起来
try {
mqttClient.connect(options);
} catch (MqttException e) {
e.getMessage();
e.printStackTrace();
}
}
}

@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.iot.framework.mqtt.consumer;
import org.eclipse.paho.client.mqttv3.MqttException;
public interface IMqttservice {
/**
*
* topic client
* */
public void subscribeMysqlTopic() throws Exception;
/**
* topic client
* */
public int subscribeTopic(String topic) throws MqttException;
/**
* topic clienttopic
* */
public int unsubscribeTopic(String topic) throws MqttException;
}

@ -0,0 +1,97 @@
package cn.iocoder.yudao.module.iot.framework.mqtt.consumer;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.iocoder.yudao.module.iot.dal.dataobject.iotorganization.IotOrganizationDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.mqttrecord.MqttRecordDO;
import cn.iocoder.yudao.module.iot.dal.mysql.mqttrecord.MqttRecordMapper;
import cn.iocoder.yudao.module.iot.framework.constant.Constants;
import cn.iocoder.yudao.module.iot.framework.mqtt.common.SuperConsumer;
import cn.iocoder.yudao.module.iot.framework.mqtt.consumer.impl.AsyncService;
import cn.iocoder.yudao.module.iot.framework.mqtt.entity.MqttData;
import cn.iocoder.yudao.module.iot.framework.mqtt.utils.DateUtils;
import cn.iocoder.yudao.module.iot.framework.mqtt.utils.MqttDataUtils;
import cn.iocoder.yudao.module.iot.service.device.DeviceService;
import cn.iocoder.yudao.module.iot.service.iotorganization.IotOrganizationService;
import cn.iocoder.yudao.module.iot.service.mqttrecord.MqttRecordService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Slf4j
@Component
public class MqttDataHandler extends SuperConsumer<String> {
@Resource
private IotOrganizationService organizationService;
@Resource
private DeviceService deviceService;
@Resource
private AsyncService asyncService;
@Resource
private MqttRecordService mqttRecordService;
@Resource
private MqttRecordMapper mqttRecordMapper;
@Override
public String decoder(MqttMessage msg) {
return new String(msg.getPayload());
}
@Override
protected void msgHandler(String topic, String entity) {
log.debug("msgHandler"+":topic="+topic);
log.debug("entity:"+entity);
MqttData data = MqttDataUtils.parse(entity);
IotOrganizationDO machine = new IotOrganizationDO();
machine.setId(1L);
if (data!=null) {
//根据设定转化
// try {
// String transfer = asyncService.transferBase(data,equipments.getEquipmentsId());
// if(StringUtils.isNotBlank(transfer))
// entity = transfer;
// }catch (Exception e){
// log.error("asyncService.transferBase error:"+entity);
// }
save(machine, entity, data);
}
}
public void save(IotOrganizationDO machine, String entity, MqttData data) {
try {
long timestamp = DateUtils.strToTimeStamp(data.getDeviceDataTime(), Constants.MQTT_timestamp_format);
//timestamp = DateUtils.getMillsLong();
LocalDateTime date = DateUtils.strToLocalDateTime(data.getDeviceDataTime());
MqttRecordDO recordDO = new MqttRecordDO();
recordDO.setDeviceCode(data.getDeviceID());
recordDO.setGatewayCode(data.getGatewayID());
recordDO.setDeviceData(entity);
recordDO.setDeviceDataTime(date);
recordDO.setDeviceDataTimeLong(timestamp);
/**直接保存原始mqtt*/
mqttRecordMapper.insert(recordDO);
/**
* mqtt
* */
//tsMqttService.insertDataAddress(data, taskId, timestamp, equipment);
} catch (Exception e) {
log.error("-----mqttTableName:");
e.printStackTrace();
}
}
}

@ -0,0 +1,150 @@
package cn.iocoder.yudao.module.iot.framework.mqtt.consumer.impl;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
import cn.iocoder.yudao.module.iot.framework.mqtt.entity.MqttData;
import cn.iocoder.yudao.module.iot.service.device.DeviceService;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import javax.annotation.Resource;
import javax.script.ScriptException;
import java.util.*;
import java.util.concurrent.TimeUnit;
@Configuration
@EnableAsync
@Slf4j
@EnableScheduling
public class AsyncService {
@Resource
private DeviceService deviceService;
/**地址转换进制*/
//@Async
// public String transferBase(MqttData data, String equipmentId) {
// //data数据改变标记
// boolean isTransfer = false;
// IoPoint vo = new IoPoint();
// vo.setEquipmentsId(equipmentId);
// vo.setDeviceId(data.getDeviceID());
// vo.setTransferDataType("---");
// List<IoPoint> pointList = ioPointService.list(ioPointService.buildQueryWrapper(vo));
// if(pointList!=null && pointList.size()>0){
// //先转进制
// for (IoPoint point: pointList) {
// if(data.getDeviceData().containsKey(point.getPointCode()) && StringUtils.isNotBlank(point.getSourceDataType())){
// String value = data.getDeviceData().get(point.getPointCode()).getV();
// //防止有些数乱填
// if(value.contains("."))continue;
// if(StringUtils.isNotBlank(value) && StringUtils.isNotBlank(point.getSourceDataType())){
// isTransfer = true;
// value = transferBase(value,point.getSourceDataType(),point.getTransferDataType());
// value = factor(value,point.getFactor());
// data.getDeviceData().get(point.getPointCode()).setV(value);
// }
// }
// }
// }
// //再进行公式计算
// Map<String, String> valueMap = getValueMap(data);
// vo.setTransferDataType("");
// vo.setCalAddresses("---");
// pointList = ioPointService.list(ioPointService.buildQueryWrapper(vo));
// for (IoPoint point: pointList) {
// if(data.getDeviceData().containsKey(point.getPointCode()) && StringUtils.isNotBlank(point.getCalAddresses())){
// try {
// isTransfer = true;
// String result = FormulaCalculator.calFormula(point.getCalAddresses(),valueMap);
// data.getDeviceData().get(point.getPointCode()).setV(result);
// } catch (ScriptException e) {
// log.error("calFormula point:"+point.toString());
// }
// }
// }
// if(isTransfer)
// return JSON.toJSONString(data);
// else
// return null;
// }
/**系数**/
private String factor(String value, String factor){
if(StringUtils.isNotBlank(factor)){
return String.format("%.2f",Double.parseDouble(value)*Double.parseDouble(factor));
}
return value;
}
private Map<String, String> getValueMap(MqttData data){
Map<String, String> valueMap = new HashMap<>();
for (String key: data.getDeviceData().keySet()){
valueMap.put(key,data.getDeviceData().get(key).getV());
}
return valueMap;
}
/**
* java valuebinary,octal,hexadecimal,decimal
* */
private String transferBase(String value,String originBase, String transferBase){
switch (transferBase){
case "decimal":{
switch (originBase){
case "binary":
value = convertBase(value,2,10);
break;
case "octal":
value = convertBase(value,8,10);
break;
case "hexadecimal":
value = convertBase(value,16,10);
case "hexfloat":
value = hexToDecimal(value);
}
}
break;
default:log.debug("数据未进行转换!:(value,originBase,transferBase)("+value+","+originBase+","+transferBase+")");
}
return value;
}
private static String hexToDecimal(String value){
return String.valueOf(Integer.parseInt(value, 16));
}
public static String convertBase(String value, int fromBase, int toBase) {
return String.valueOf(Integer.parseInt(value, fromBase));
}
public static void main(String[] args) {
String value = "479624"; // 要转换的值
int fromBase = 16; // 起始进制
int toBase = 10; // 目标进制
String convertedValue = convertBase(value, fromBase, toBase);
System.out.println("Converted value: " + convertedValue);
int intValue = Integer.parseInt(value, 16); // 将十六进制字符串解析为十进制整数
System.out.println(intValue);
intValue = Integer.parseInt("476c", 16); // 将十六进制字符串解析为十进制整数
System.out.println(intValue);
// 获取当前日期
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
Date date = calendar.getTime();
long timestamp = date.getTime() / 1000; // 将时间戳转换为秒
System.out.println("当天 00:00:00 的时间戳:" + timestamp);
}
}

@ -0,0 +1,111 @@
package cn.iocoder.yudao.module.iot.framework.mqtt.consumer.impl;
import cn.iocoder.yudao.module.iot.dal.dataobject.gateway.GatewayDO;
import cn.iocoder.yudao.module.iot.framework.constant.IsEnableConstant;
import cn.iocoder.yudao.module.iot.framework.mqtt.common.MqttCallbackImpl;
import cn.iocoder.yudao.module.iot.framework.mqtt.config.DefaultBizTopicSet;
import cn.iocoder.yudao.module.iot.framework.mqtt.consumer.IMqttservice;
import cn.iocoder.yudao.module.iot.framework.mqtt.consumer.MqttDataHandler;
import cn.iocoder.yudao.module.iot.framework.mqtt.entity.Pattern;
import cn.iocoder.yudao.module.iot.framework.mqtt.entity.SubscriptTopic;
import cn.iocoder.yudao.module.iot.service.gateway.GatewayService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.DependsOn;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
@EnableScheduling
@DependsOn("defaultMqttStarter")
@Slf4j
public class MqttserviceImpl implements IMqttservice, ApplicationListener<ApplicationReadyEvent> {
@Resource
private GatewayService gatewayService;
@Resource
private MqttClient client;
@Resource
private DefaultBizTopicSet defaultBizTopicSet;
@Resource
private MqttConnectOptions options;
@Resource
private MqttDataHandler dataHandler;
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
new Thread(() -> {
subscribeMysqlTopic();
}).start();
}
/**
*
* topic client
* */
@Override
public void subscribeMysqlTopic(){
if(client.isConnected()){
List<GatewayDO> 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 clienttopic
* */
@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;
}
}

@ -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;
/**
* <p> 线
* :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;
}

@ -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;
/**
* <p>线
* @author jie
*/
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Disconnect {
/**
* id
*/
private String clientid;
/**
*
*/
private String username;
/**
*
*/
private String reason;
/**
* (ms)
*/
private long ts;
}

@ -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;
}

@ -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<String,IoData> deviceData;
protected String deviceDataTime;
}

@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.iot.framework.mqtt.entity;
/**
*
* @author jie
*/
public enum Pattern {
/**
*
*/
NONE,
/**
*
*/
QUEUE,
/**
*
*/
SHARE;
}

@ -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;
}

@ -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
* :
* <p>
* <p>bean
*/
@Component
public class ApplicationContextUtil {
private static ApplicationContextUtil instance;
@Autowired
private ApplicationContext applicationContext;
@PostConstruct
public void applicationContextUtil() {
instance = this;
}
/**
* bean
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(Class<T> clazz) {
return instance.applicationContext.getBean(clazz);
}
/**
* bean
* @param name
* @param <T>
* @return
* @throws BeansException
*/
public static <T> T getBean(String name) throws BeansException {
return (T) instance.applicationContext.getBean(name);
}
}

@ -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;
}
}

@ -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;
}
}

@ -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;
}
}

@ -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);
}

@ -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:";
}

@ -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<GatewayDO> selectListByIsEnable(boolean isEnable);
/**
*
*
@ -93,4 +96,5 @@ public interface GatewayService {
*/
DeviceDO getDevice(Long id);
}

@ -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<GatewayDO> selectListByIsEnable(boolean isEnable){
return gatewayMapper.selectListByIsEnable(isEnable);
}
@Override
public PageResult<GatewayDO> getGatewayPage(GatewayPageReqVO pageReqVO) {
return gatewayMapper.selectPage(pageReqVO);

@ -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
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 #心跳间隔
Loading…
Cancel
Save