代码优化,上线离线
This commit is contained in:
@@ -11,6 +11,18 @@
|
|||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
|
<version>4.0.0</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.dromara.mica-mqtt</groupId>
|
<groupId>org.dromara.mica-mqtt</groupId>
|
||||||
@@ -54,21 +66,29 @@
|
|||||||
<version>3.5.14</version>
|
<version>3.5.14</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!-- <!– MySQL Connector –>-->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>mysql</groupId>
|
<groupId>mysql</groupId>
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
<version>8.0.33</version>
|
<version>8.0.33</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- <!– Druid Connection Pool –>-->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
<artifactId>druid-spring-boot-starter</artifactId>
|
<artifactId>druid-spring-boot-starter</artifactId>
|
||||||
<version>1.2.20</version>
|
<version>1.2.20</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- SpringBoot Boot Redis -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.dromara.mica.mqtt.server;
|
package org.dromara.mica.mqtt.server;
|
||||||
|
|
||||||
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
@@ -9,6 +10,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
|
|||||||
*/
|
*/
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@EnableScheduling
|
@EnableScheduling
|
||||||
|
@MapperScan("org.dromara.mica.mqtt.server.mapper")
|
||||||
public class MqttServerApplication {
|
public class MqttServerApplication {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2018 人人开源 All rights reserved.
|
||||||
|
*
|
||||||
|
* https://www.renren.io
|
||||||
|
*
|
||||||
|
* 版权所有,侵权必究!
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.mica.mqtt.server.config;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mybatis-plus配置
|
||||||
|
*
|
||||||
|
* @author Mark sunlightcs@gmail.com
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class MybatisPlusConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置分页等
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||||
|
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
|
||||||
|
// 乐观锁
|
||||||
|
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
|
||||||
|
|
||||||
|
return mybatisPlusInterceptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||||
|
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
||||||
|
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||||
|
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class RedisConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
|
||||||
|
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
|
||||||
|
redisTemplate.setConnectionFactory(factory);
|
||||||
|
//使用jackson进行序列化
|
||||||
|
Jackson2JsonRedisSerializer jsonRedisSerializer =
|
||||||
|
new Jackson2JsonRedisSerializer(Object.class);
|
||||||
|
//规定序列化规则
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
/**
|
||||||
|
* 第一个参数指的是序列化的域,ALL指的是字段、get和set方法、构造方法
|
||||||
|
* 第二个参数指的是序列化哪些访问修饰符,默认是public,ANY指任何访问修饰符
|
||||||
|
*/
|
||||||
|
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
||||||
|
//指定序列化输入的类型,类必须是非final修饰的类
|
||||||
|
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
|
||||||
|
jsonRedisSerializer.setObjectMapper(objectMapper);
|
||||||
|
//序列化key value
|
||||||
|
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||||
|
redisTemplate.setValueSerializer(jsonRedisSerializer);
|
||||||
|
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
|
||||||
|
redisTemplate.setHashValueSerializer(jsonRedisSerializer);
|
||||||
|
redisTemplate.afterPropertiesSet();
|
||||||
|
return redisTemplate;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,22 +1,31 @@
|
|||||||
package org.dromara.mica.mqtt.server.controller;
|
package org.dromara.mica.mqtt.server.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.dromara.mica.mqtt.server.entity.CarInfo;
|
import org.dromara.mica.mqtt.server.entity.CarInfo;
|
||||||
|
import org.dromara.mica.mqtt.server.redis.RedisService;
|
||||||
import org.dromara.mica.mqtt.server.service.ICarInfoService;
|
import org.dromara.mica.mqtt.server.service.ICarInfoService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/car")
|
@RequestMapping("/car")
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class CarInfoController {
|
public class CarInfoController {
|
||||||
|
|
||||||
private final ICarInfoService carInfoService;
|
@Autowired
|
||||||
|
ICarInfoService carInfoService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
RedisService redisService;
|
||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public List<CarInfo> list() {
|
public List<CarInfo> list() {
|
||||||
return carInfoService.list();
|
return carInfoService.list();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package org.dromara.mica.mqtt.server.controller;
|
|||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import org.dromara.mica.mqtt.server.service.ServerService;
|
import org.dromara.mica.mqtt.server.service.impl.ServerService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|||||||
@@ -1,12 +1,64 @@
|
|||||||
package org.dromara.mica.mqtt.server.entity;
|
package org.dromara.mica.mqtt.server.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@TableName("car_info")
|
@TableName("car_info")
|
||||||
public class CarInfo {
|
public class CarInfo implements Serializable {
|
||||||
private Long customerId;
|
@Serial
|
||||||
private String plate;
|
private static final long serialVersionUID = 1L;
|
||||||
private String enable;
|
|
||||||
|
/** customer_id */
|
||||||
|
private Long customerId;
|
||||||
|
|
||||||
|
/** 白名单生效时间 */
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date enableTime;
|
||||||
|
|
||||||
|
/** 白名单失效时间 */
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date overdueTime;
|
||||||
|
|
||||||
|
/** 是否启动 */
|
||||||
|
private String enable;
|
||||||
|
|
||||||
|
/** 车牌号 */
|
||||||
|
private String plate;
|
||||||
|
|
||||||
|
/** 是否启用时间段 */
|
||||||
|
private String timeSegEnable;
|
||||||
|
|
||||||
|
/** 时间段 */
|
||||||
|
private String segTime;
|
||||||
|
|
||||||
|
/** 是否需要报警 */
|
||||||
|
private String needAlarm;
|
||||||
|
|
||||||
|
/** 用户自定义代码 */
|
||||||
|
private String vehicleCode;
|
||||||
|
|
||||||
|
/** 用户自定义的注释 */
|
||||||
|
private String vehicleComment;
|
||||||
|
|
||||||
|
/** 所属人员 */
|
||||||
|
private Long peopleId;
|
||||||
|
|
||||||
|
/** 是否删除 0 是未删除 2是删除 */
|
||||||
|
private String delFlag;
|
||||||
|
|
||||||
|
/** 同步标识 sync 0是未同步 1是已同步 */
|
||||||
|
private String sync;
|
||||||
|
|
||||||
|
private String sn;//设备序列号
|
||||||
|
|
||||||
|
private int num;
|
||||||
|
|
||||||
|
/** 超频设备识别标签 */
|
||||||
|
private String overclockCard;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("sys_equipment")
|
||||||
|
public class Equipment implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|
||||||
|
/** 设备Id */
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/** 所属产品Id */
|
||||||
|
private Long productId;
|
||||||
|
|
||||||
|
/** 设备名称 */
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/** 设备序列号 */
|
||||||
|
private String sequence;
|
||||||
|
|
||||||
|
/** 设备Ip */
|
||||||
|
private String ip;
|
||||||
|
|
||||||
|
/** 设备密码 */
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
/** 设备区域 */
|
||||||
|
private Long spaceId;
|
||||||
|
|
||||||
|
/** 设备位置 */
|
||||||
|
private Long pointId;
|
||||||
|
|
||||||
|
/** 对接状态(0未对接 1对接成功) */
|
||||||
|
private Long state;
|
||||||
|
|
||||||
|
/** 设备状态(0在线 1离线) */
|
||||||
|
private String flag;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.listener;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dromara.mica.mqtt.codec.message.MqttPublishMessage;
|
||||||
|
import org.dromara.mica.mqtt.server.pojo.User;
|
||||||
|
import org.dromara.mica.mqtt.core.annotation.MqttServerFunction;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.tio.core.ChannelContext;
|
||||||
|
import org.tio.core.Node;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息监听器
|
||||||
|
*
|
||||||
|
* @author wsq
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class CarMessageListener {
|
||||||
|
|
||||||
|
|
||||||
|
@MqttServerFunction("device/${sn}/message/up/keep_alive")
|
||||||
|
public void onKeepAliveMessage(String topic, Map<String, String> topicVars, byte[] message) {
|
||||||
|
log.info("onKeepAliveMessage topic:{}", topic);
|
||||||
|
log.info("onKeepAliveMessage topicVars:{}", topicVars);
|
||||||
|
log.info("接收到心跳消息 -> Topic: {}, Payload: {}", topic, new String(message));
|
||||||
|
// 在这里添加您的业务逻辑,例如:
|
||||||
|
// 1. 解析 payload
|
||||||
|
// 2. 更新设备在线状态
|
||||||
|
// 3. 回复心跳响应等
|
||||||
|
}
|
||||||
|
|
||||||
|
@MqttServerFunction("device/${sn}/message/down/white_list_operator/reply")
|
||||||
|
public void white_list_operator_reply(String topic, byte[] payload) {
|
||||||
|
log.info("接收到消息 -> Topic: {}, Payload: {}", topic, new String(payload));
|
||||||
|
// 在这里添加您的业务逻辑,例如:
|
||||||
|
// 1. 解析 payload
|
||||||
|
// 2. 更新设备在线状态
|
||||||
|
// 3. 回复心跳响应等
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -16,8 +16,13 @@
|
|||||||
|
|
||||||
package org.dromara.mica.mqtt.server.listener;
|
package org.dromara.mica.mqtt.server.listener;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.dromara.mica.mqtt.core.server.event.IMqttConnectStatusListener;
|
import org.dromara.mica.mqtt.core.server.event.IMqttConnectStatusListener;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.Equipment;
|
||||||
|
import org.dromara.mica.mqtt.server.mapper.EquipmentMapper;
|
||||||
|
import org.dromara.mica.mqtt.server.service.IEquipmentService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.tio.core.ChannelContext;
|
import org.tio.core.ChannelContext;
|
||||||
|
|
||||||
@@ -30,13 +35,25 @@ import org.tio.core.ChannelContext;
|
|||||||
@Service
|
@Service
|
||||||
public class MqttConnectStatusListener2 implements IMqttConnectStatusListener {
|
public class MqttConnectStatusListener2 implements IMqttConnectStatusListener {
|
||||||
|
|
||||||
|
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(MqttConnectStatusListener2.class);
|
||||||
|
@Autowired
|
||||||
|
EquipmentMapper equipmentMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void online(ChannelContext context, String clientId, String username) {
|
public void online(ChannelContext context, String clientId, String username) {
|
||||||
log.info("Mqtt clientId:{} username:{} online.", clientId, username);
|
log.info("online-context: {}", context);
|
||||||
|
Equipment equipment = new Equipment();
|
||||||
|
equipment.setFlag("0");
|
||||||
|
equipmentMapper.update(equipment, new QueryWrapper<Equipment>().eq("sequence", clientId).eq("product_id", 4L));
|
||||||
|
log.info("设备:{}上线", clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void offline(ChannelContext context, String clientId, String username, String reason) {
|
public void offline(ChannelContext context, String clientId, String username, String reason) {
|
||||||
log.info("Mqtt clientId:{} username:{} offline reason:{}.", clientId, username, reason);
|
log.info("offline-context: {}", context);
|
||||||
|
Equipment equipment = new Equipment();
|
||||||
|
equipment.setFlag("1");
|
||||||
|
equipmentMapper.update(equipment, new QueryWrapper<Equipment>().eq("sequence", clientId).eq("product_id", 4L));
|
||||||
|
log.info("设备:{}离线,offline reason:{}.", clientId, reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
package org.dromara.mica.mqtt.server.listener;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.dromara.mica.mqtt.codec.message.MqttPublishMessage;
|
|
||||||
import org.dromara.mica.mqtt.server.pojo.User;
|
|
||||||
import org.dromara.mica.mqtt.core.annotation.MqttServerFunction;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.tio.core.ChannelContext;
|
|
||||||
import org.tio.core.Node;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 消息监听器示例2,MqttServerFunction 注解订阅,注意:如果自行实现了 IMqttMessageListener,MqttServerFunction 注解就不生效了。
|
|
||||||
*
|
|
||||||
* @author wsq
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Service
|
|
||||||
public class MqttServerMessageListener2 {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MQTT消息处理函数
|
|
||||||
*
|
|
||||||
* @param topic mqtt Topic
|
|
||||||
* @param user 订阅消息的负载内容,默认 json 序列化
|
|
||||||
*/
|
|
||||||
@MqttServerFunction("/test/object")
|
|
||||||
public void func1(String topic, User<?> user) {
|
|
||||||
log.info("topic:{} user:{}", topic, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
@MqttServerFunction("/test/client")
|
|
||||||
public void func2(String topic, byte[] message) {
|
|
||||||
log.info("topic:{} message:{}", topic, new String(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MQTT消息处理函数,匹配 mqtt Topic /test/+,如何需要匹配所以消息,请使用通配符 #
|
|
||||||
*
|
|
||||||
* @param context ChannelContext,可选参数
|
|
||||||
* @param topic 实际接收到消息的主题名称,可选参数
|
|
||||||
* @param topicVars topic 中的 ${xxxx} 变量解析(v2.5.4支持),可选参数,注意:类型必须为 Map<String, String>
|
|
||||||
* @param publishMessage 完整的MQTT发布消息对象,包含消息头和负载,可选参数
|
|
||||||
* @param message 消息负载内容,以字节数组形式提供,可选参数,也可支持对象形式,默认 json 序列化
|
|
||||||
*/
|
|
||||||
@MqttServerFunction("/test/${xxxx}")
|
|
||||||
public void func3(ChannelContext context, String topic, Map<String, String> topicVars, MqttPublishMessage publishMessage, byte[] message) {
|
|
||||||
// 获取客户端节点信息
|
|
||||||
Node clientNode = context.getClientNode();
|
|
||||||
// 记录接收到的MQTT消息信息
|
|
||||||
log.info("clientNode:{} topic:{} topicVars:{} publishMessage:{} message:{}", clientNode, topic, topicVars, publishMessage, new String(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.CarInfo;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.Equipment;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface EquipmentMapper extends BaseMapper<Equipment> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,302 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.redis;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.BoundSetOperations;
|
||||||
|
import org.springframework.data.redis.core.HashOperations;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.core.ValueOperations;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class RedisService {
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public RedisTemplate redisTemplate;
|
||||||
|
|
||||||
|
private static final long DEFAULT_TIMEOUT = 60 * 60 * 24 * 7;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存基本的对象,Integer、String、实体类等
|
||||||
|
*
|
||||||
|
* @param key 缓存的键值
|
||||||
|
* @param value 缓存的值
|
||||||
|
*/
|
||||||
|
public <T> void setCacheObject(final String key, final T value)
|
||||||
|
{
|
||||||
|
redisTemplate.opsForValue().set(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存是否存在,存在返回false,不存在返回true并存储缓存值
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public Boolean setIfAbsent(final String key, final String value, long timeout, TimeUnit timeUnit)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return redisTemplate.opsForValue().setIfAbsent(key, value, timeout, timeUnit);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("redis error:{}", e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分布式加锁
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public Boolean lock(final String key, final String value, long timeout, TimeUnit timeUnit)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (timeout <= 0) {
|
||||||
|
timeout = DEFAULT_TIMEOUT;
|
||||||
|
timeUnit = TimeUnit.SECONDS;
|
||||||
|
}
|
||||||
|
return redisTemplate.opsForValue().setIfAbsent(key, value, timeout, timeUnit);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("redis error:{}", e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存基本的对象,Integer、String、实体类等
|
||||||
|
*
|
||||||
|
* @param key 缓存的键值
|
||||||
|
* @param value 缓存的值
|
||||||
|
* @param timeout 时间
|
||||||
|
* @param timeUnit 时间颗粒度
|
||||||
|
*/
|
||||||
|
public <T> void setCacheObject(final String key, final T value, final Long timeout, final TimeUnit timeUnit)
|
||||||
|
{
|
||||||
|
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置有效时间
|
||||||
|
*
|
||||||
|
* @param key Redis键
|
||||||
|
* @param timeout 超时时间
|
||||||
|
* @return true=设置成功;false=设置失败
|
||||||
|
*/
|
||||||
|
public boolean expire(final String key, final long timeout)
|
||||||
|
{
|
||||||
|
return expire(key, timeout, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置有效时间
|
||||||
|
*
|
||||||
|
* @param key Redis键
|
||||||
|
* @param timeout 超时时间
|
||||||
|
* @param unit 时间单位
|
||||||
|
* @return true=设置成功;false=设置失败
|
||||||
|
*/
|
||||||
|
public boolean expire(final String key, final long timeout, final TimeUnit unit)
|
||||||
|
{
|
||||||
|
return redisTemplate.expire(key, timeout, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取有效时间
|
||||||
|
*
|
||||||
|
* @param key Redis键
|
||||||
|
* @return 有效时间
|
||||||
|
*/
|
||||||
|
public long getExpire(final String key)
|
||||||
|
{
|
||||||
|
return redisTemplate.getExpire(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断 key是否存在
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @return true 存在 false不存在
|
||||||
|
*/
|
||||||
|
public Boolean hasKey(String key)
|
||||||
|
{
|
||||||
|
return redisTemplate.hasKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得缓存的基本对象。
|
||||||
|
*
|
||||||
|
* @param key 缓存键值
|
||||||
|
* @return 缓存键值对应的数据
|
||||||
|
*/
|
||||||
|
public <T> T getCacheObject(final String key)
|
||||||
|
{
|
||||||
|
ValueOperations<String, T> operation = redisTemplate.opsForValue();
|
||||||
|
return operation.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除单个对象
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
public boolean deleteObject(final String key)
|
||||||
|
{
|
||||||
|
return redisTemplate.delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除集合对象
|
||||||
|
*
|
||||||
|
* @param collection 多个对象
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean deleteObject(final Collection collection)
|
||||||
|
{
|
||||||
|
return redisTemplate.delete(collection) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存List数据
|
||||||
|
*
|
||||||
|
* @param key 缓存的键值
|
||||||
|
* @param dataList 待缓存的List数据
|
||||||
|
* @return 缓存的对象
|
||||||
|
*/
|
||||||
|
public <T> long setCacheList(final String key, final List<T> dataList)
|
||||||
|
{
|
||||||
|
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
|
||||||
|
return count == null ? 0 : count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得缓存的list对象
|
||||||
|
*
|
||||||
|
* @param key 缓存的键值
|
||||||
|
* @return 缓存键值对应的数据
|
||||||
|
*/
|
||||||
|
public <T> List<T> getCacheList(final String key)
|
||||||
|
{
|
||||||
|
return redisTemplate.opsForList().range(key, 0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存Set
|
||||||
|
*
|
||||||
|
* @param key 缓存键值
|
||||||
|
* @param dataSet 缓存的数据
|
||||||
|
* @return 缓存数据的对象
|
||||||
|
*/
|
||||||
|
public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
|
||||||
|
{
|
||||||
|
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
|
||||||
|
Iterator<T> it = dataSet.iterator();
|
||||||
|
while (it.hasNext())
|
||||||
|
{
|
||||||
|
setOperation.add(it.next());
|
||||||
|
}
|
||||||
|
return setOperation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得缓存的set
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public <T> Set<T> getCacheSet(final String key)
|
||||||
|
{
|
||||||
|
return redisTemplate.opsForSet().members(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存Map
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param dataMap
|
||||||
|
*/
|
||||||
|
public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
|
||||||
|
{
|
||||||
|
if (dataMap != null) {
|
||||||
|
redisTemplate.opsForHash().putAll(key, dataMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得缓存的Map
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public <T> Map<String, T> getCacheMap(final String key)
|
||||||
|
{
|
||||||
|
return redisTemplate.opsForHash().entries(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 往Hash中存入数据
|
||||||
|
*
|
||||||
|
* @param key Redis键
|
||||||
|
* @param hKey Hash键
|
||||||
|
* @param value 值
|
||||||
|
*/
|
||||||
|
public <T> void setCacheMapValue(final String key, final String hKey, final T value)
|
||||||
|
{
|
||||||
|
redisTemplate.opsForHash().put(key, hKey, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Hash中的数据
|
||||||
|
*
|
||||||
|
* @param key Redis键
|
||||||
|
* @param hKey Hash键
|
||||||
|
* @return Hash中的对象
|
||||||
|
*/
|
||||||
|
public <T> T getCacheMapValue(final String key, final String hKey)
|
||||||
|
{
|
||||||
|
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
|
||||||
|
return opsForHash.get(key, hKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取多个Hash中的数据
|
||||||
|
*
|
||||||
|
* @param key Redis键
|
||||||
|
* @param hKeys Hash键集合
|
||||||
|
* @return Hash对象集合
|
||||||
|
*/
|
||||||
|
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
|
||||||
|
{
|
||||||
|
return redisTemplate.opsForHash().multiGet(key, hKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除Hash中的某条数据
|
||||||
|
*
|
||||||
|
* @param key Redis键
|
||||||
|
* @param hKey Hash键
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
public boolean deleteCacheMapValue(final String key, final String hKey)
|
||||||
|
{
|
||||||
|
return redisTemplate.opsForHash().delete(key, hKey) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得缓存的基本对象列表
|
||||||
|
*
|
||||||
|
* @param pattern 字符串前缀
|
||||||
|
* @return 对象列表
|
||||||
|
*/
|
||||||
|
public Collection<String> keys(final String pattern)
|
||||||
|
{
|
||||||
|
return redisTemplate.keys(pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,4 +4,6 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
|||||||
import org.dromara.mica.mqtt.server.entity.CarInfo;
|
import org.dromara.mica.mqtt.server.entity.CarInfo;
|
||||||
|
|
||||||
public interface ICarInfoService extends IService<CarInfo> {
|
public interface ICarInfoService extends IService<CarInfo> {
|
||||||
|
|
||||||
|
CarInfo selectCarInfoBySn(String sn);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.Equipment;
|
||||||
|
|
||||||
|
public interface IEquipmentService extends IService<Equipment> {
|
||||||
|
|
||||||
|
Equipment selectEquipmentBySn(String sn);
|
||||||
|
}
|
||||||
@@ -1,11 +1,23 @@
|
|||||||
package org.dromara.mica.mqtt.server.service.impl;
|
package org.dromara.mica.mqtt.server.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.dromara.mica.mqtt.server.entity.CarInfo;
|
import org.dromara.mica.mqtt.server.entity.CarInfo;
|
||||||
import org.dromara.mica.mqtt.server.mapper.CarInfoMapper;
|
import org.dromara.mica.mqtt.server.mapper.CarInfoMapper;
|
||||||
import org.dromara.mica.mqtt.server.service.ICarInfoService;
|
import org.dromara.mica.mqtt.server.service.ICarInfoService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class CarInfoServiceImpl extends ServiceImpl<CarInfoMapper, CarInfo> implements ICarInfoService {
|
public class CarInfoServiceImpl extends ServiceImpl<CarInfoMapper, CarInfo> implements ICarInfoService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
CarInfoMapper carInfoMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CarInfo selectCarInfoBySn(String sn) {
|
||||||
|
carInfoMapper.selectOne(new QueryWrapper<CarInfo>().eq("sequence", sn));
|
||||||
|
|
||||||
|
return new CarInfo();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.Equipment;
|
||||||
|
import org.dromara.mica.mqtt.server.mapper.EquipmentMapper;
|
||||||
|
import org.dromara.mica.mqtt.server.service.IEquipmentService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class EquipmentServiceImpl extends ServiceImpl<EquipmentMapper, Equipment> implements IEquipmentService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
EquipmentMapper equipmentMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Equipment selectEquipmentBySn(String sn) {
|
||||||
|
return equipmentMapper.selectOne(new QueryWrapper<Equipment>().eq("sequence", sn).eq("product_id", 4L).last("limit 1"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.dromara.mica.mqtt.server.service;
|
package org.dromara.mica.mqtt.server.service.impl;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.dromara.mica.mqtt.spring.server.MqttServerTemplate;
|
import org.dromara.mica.mqtt.spring.server.MqttServerTemplate;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.utils;
|
||||||
|
|
||||||
|
public class SNUtils {
|
||||||
|
|
||||||
|
public String getSn(String topic) {
|
||||||
|
return topic;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
url: jdbc:mysql://127.0.0.1:3306/xa_cloud?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
|
||||||
|
username: root
|
||||||
|
password: root
|
||||||
|
data:
|
||||||
|
redis:
|
||||||
|
host: 192.168.2.30
|
||||||
|
password: redis2025
|
||||||
|
database: 5
|
||||||
|
port: 6379
|
||||||
@@ -1,32 +1,57 @@
|
|||||||
server:
|
server:
|
||||||
port: 30013
|
port: 30013
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
application:
|
application:
|
||||||
name: mica-mqtt-server
|
name: mica-mqtt-server
|
||||||
|
# 环境 dev|test|prod
|
||||||
|
profiles:
|
||||||
|
active: dev
|
||||||
|
# active: prod
|
||||||
|
messages:
|
||||||
|
encoding: UTF-8
|
||||||
|
basename: i18n/messages
|
||||||
|
# jackson时间格式化
|
||||||
|
jackson:
|
||||||
|
time-zone: GMT+8
|
||||||
|
date-format: yyyy-MM-dd HH:mm:ss
|
||||||
|
mvc:
|
||||||
|
pathmatch:
|
||||||
|
matching-strategy: ANT_PATH_MATCHER
|
||||||
|
servlet:
|
||||||
|
multipart:
|
||||||
|
max-file-size: 100MB
|
||||||
|
max-request-size: 100MB
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
|
||||||
|
#mybatis-plus:
|
||||||
|
# configuration:
|
||||||
|
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||||
|
|
||||||
|
#mybatis
|
||||||
|
#mybatis-plus:
|
||||||
|
# mapper-locations: classpath*:/mapper/**/*.xml
|
||||||
|
# #实体扫描,多个package用逗号或者分号分隔
|
||||||
|
# typeAliasesPackage: io.renren.entity
|
||||||
|
# global-config:
|
||||||
|
# #数据库相关配置
|
||||||
|
# db-config:
|
||||||
|
# #主键类型
|
||||||
|
# id-type: ASSIGN_ID
|
||||||
|
# banner: false
|
||||||
|
# #原生配置
|
||||||
|
# configuration:
|
||||||
|
# map-underscore-to-camel-case: true
|
||||||
|
# cache-enabled: false
|
||||||
|
# call-setters-on-nulls: true
|
||||||
|
# jdbc-type-for-null: 'null'
|
||||||
|
# configuration-properties:
|
||||||
|
# prefix:
|
||||||
|
# blobType: BLOB
|
||||||
|
# boolValue: TRUE
|
||||||
|
|
||||||
datasource:
|
|
||||||
url: jdbc:mysql://127.0.0.1:3306/xa_cloud?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
|
|
||||||
username: root
|
|
||||||
password: root
|
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
|
||||||
type: com.alibaba.druid.pool.DruidDataSource
|
|
||||||
|
|
||||||
#mybatis
|
|
||||||
mybatis-plus:
|
|
||||||
mapper-locations: classpath:/mapper/**/*.xml
|
|
||||||
#实体扫描,多个package用逗号或者分号分隔
|
|
||||||
typeAliasesPackage: org.dromara.mica.mqtt.server.entity
|
|
||||||
global-config:
|
|
||||||
#数据库相关配置
|
|
||||||
db-config:
|
|
||||||
#主键类型
|
|
||||||
id-type: ASSIGN_ID
|
|
||||||
banner: false
|
|
||||||
#原生配置
|
|
||||||
configuration:
|
|
||||||
map-underscore-to-camel-case: true
|
|
||||||
#打印日志
|
|
||||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
|
||||||
|
|
||||||
# mqtt 服务端配置
|
# mqtt 服务端配置
|
||||||
mqtt:
|
mqtt:
|
||||||
@@ -76,11 +101,13 @@ mqtt:
|
|||||||
password: mica
|
password: mica
|
||||||
mcp-server: # 大模型 mcp
|
mcp-server: # 大模型 mcp
|
||||||
enable: true
|
enable: true
|
||||||
|
|
||||||
springdoc:
|
springdoc:
|
||||||
swagger-ui:
|
swagger-ui:
|
||||||
urls:
|
urls:
|
||||||
- name: swagger
|
- name: swagger
|
||||||
url: /v3/api-docs
|
url: /v3/api-docs
|
||||||
|
|
||||||
# actuator management
|
# actuator management
|
||||||
management:
|
management:
|
||||||
info:
|
info:
|
||||||
@@ -98,6 +125,7 @@ management:
|
|||||||
web:
|
web:
|
||||||
exposure:
|
exposure:
|
||||||
include: '*'
|
include: '*'
|
||||||
|
|
||||||
logging:
|
logging:
|
||||||
level:
|
level:
|
||||||
root: info
|
root: info
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="org.dromara.mica.mqtt.server.mapper.CarInfoMapper">
|
||||||
|
|
||||||
|
</mapper>
|
||||||
Reference in New Issue
Block a user