2 Commits

Author SHA1 Message Date
ed180d6f18 集成MQTT,优化代码 2025-06-27 10:30:27 +08:00
c0c33f6c2e 集成MQTT 2025-06-26 17:14:34 +08:00
27 changed files with 406 additions and 110 deletions

View File

@ -38,5 +38,4 @@ public interface GenConfigService extends IService<GenConfig> {
* @return 表配置 * @return 表配置
*/ */
GenConfig update(String tableName, GenConfig genConfig); GenConfig update(String tableName, GenConfig genConfig);
} }

View File

@ -0,0 +1,33 @@
package com.fuyuanshen.modules.mqtt.config;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
/**
* @Author: HarryLin
* @Date: 2025/3/20 14:40
* @Company: 北京红山信息科技研究院有限公司
* @Email: linyun@***.com.cn
**/
@Configuration
public class MqttConfiguration {
@Autowired
private MqttPropertiesConfig mqttPropertiesConfig;
/** 创建连接工厂 **/
@Bean
public MqttPahoClientFactory mqttPahoClientFactory(){
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(true); //设置新会话
options.setUserName(mqttPropertiesConfig.getUsername());
options.setPassword(mqttPropertiesConfig.getPassword().toCharArray());
options.setServerURIs(new String[]{mqttPropertiesConfig.getUrl()});
factory.setConnectionOptions(options);
return factory;
}
}

View File

@ -0,0 +1,17 @@
package com.fuyuanshen.modules.mqtt.config;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.handler.annotation.Header;
/**
* @Author: HarryLin
* @Date: 2025/3/20 17:06
* @Company: 北京红山信息科技研究院有限公司
* @Email: linyun@***.com.cn
**/
@MessagingGateway(defaultRequestChannel = "mqttOutboundChannel")
public interface MqttGateway {
public abstract void sendMsgToMqtt(@Header(value = MqttHeaders.TOPIC) String topic, String payload);
public abstract void sendMsgToMqtt(@Header(value = MqttHeaders.TOPIC) String topic, @Header(value = MqttHeaders.QOS) int qos, String payload );
}

View File

@ -0,0 +1,60 @@
package com.fuyuanshen.modules.mqtt.config;
import com.fuyuanshen.modules.mqtt.receiver.ReceiverMessageHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
/**
* @Author: HarryLin
* @Date: 2025/3/20 14:54
* @Company: 北京红山信息科技研究院有限公司
* @Email: linyun@***.com.cn
**/
@Configuration
public class MqttInboundConfiguration {
@Autowired
private MqttPropertiesConfig mqttPropertiesConfig;
@Autowired
private MqttPahoClientFactory mqttPahoClientFactory;
@Autowired
private ReceiverMessageHandler receiverMessageHandler;
//消息通道
@Bean
public MessageChannel messageInboundChannel(){
return new DirectChannel();
}
/**
* 配置入站适配器
* 作用: 设置订阅主题,以及指定消息的通道 等相关属性
* */
@Bean
public MessageProducer messageProducer(){
MqttPahoMessageDrivenChannelAdapter mqttPahoMessageDrivenChannelAdapter = new MqttPahoMessageDrivenChannelAdapter(
mqttPropertiesConfig.getUrl(),
mqttPropertiesConfig.getSubClientId(),
mqttPahoClientFactory,
mqttPropertiesConfig.getSubTopic().split(",")
);
mqttPahoMessageDrivenChannelAdapter.setQos(1);
mqttPahoMessageDrivenChannelAdapter.setConverter(new DefaultPahoMessageConverter());
mqttPahoMessageDrivenChannelAdapter.setOutputChannel(messageInboundChannel());
return mqttPahoMessageDrivenChannelAdapter;
}
/** 指定处理消息来自哪个通道 */
@Bean
@ServiceActivator(inputChannel = "messageInboundChannel")
public MessageHandler messageHandler(){
return receiverMessageHandler;
}
}

View File

@ -0,0 +1,50 @@
package com.fuyuanshen.modules.mqtt.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
/**
* @Author: HarryLin
* @Date: 2025/3/20 15:46
* @Company: 北京红山信息科技研究院有限公司
* @Email: linyun@***.com.cn
**/
@Configuration
@Slf4j
public class MqttOutboundConfiguration {
@Autowired
private MqttPropertiesConfig mqttPropertiesConfig;
@Autowired
private MqttPahoClientFactory mqttPahoClientFactory;
// 消息通道
@Bean
public MessageChannel mqttOutboundChannel(){
return new DirectChannel();
}
/** 配置出站消息处理器 */
@Bean
@ServiceActivator(inputChannel = "mqttOutboundChannel") // 指定处理器针对哪个通道的消息进行处理
public MessageHandler mqttOutboundMessageHandler(){
MqttPahoMessageHandler mqttPahoMessageHandler = new MqttPahoMessageHandler(
mqttPropertiesConfig.getUrl(),
mqttPropertiesConfig.getPubClientId(),
mqttPahoClientFactory
);
mqttPahoMessageHandler.setDefaultQos(1);
mqttPahoMessageHandler.setDefaultTopic("worker/location");
mqttPahoMessageHandler.setAsync(true);
return mqttPahoMessageHandler;
}
}

View File

@ -0,0 +1,24 @@
package com.fuyuanshen.modules.mqtt.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @Author: HarryLin
* @Date: 2025/3/20 14:32
* @Company: 北京红山信息科技研究院有限公司
* @Email: linyun@***.com.cn
**/
@Data
@ConfigurationProperties(prefix = "mqtt")
@Component
public class MqttPropertiesConfig {
private String username;
private String password;
private String url;
private String subClientId;
private String subTopic;
private String pubClientId;
private String pubTopic;
}

View File

@ -0,0 +1,25 @@
package com.fuyuanshen.modules.mqtt.publish;
import com.fuyuanshen.annotation.rest.AnonymousGetMapping;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/device")
@Slf4j
public class DeviceDataController {
@Autowired
private MqttClientTest mqttClientTest;
// @PostMapping("/{deviceId}/command")
@AnonymousGetMapping(value = "/test/command")
public ResponseEntity<String> sendCommand() {
mqttClientTest.sendMsg();
return ResponseEntity.ok("success");
}
}

View File

@ -0,0 +1,22 @@
package com.fuyuanshen.modules.mqtt.publish;
import com.fuyuanshen.modules.mqtt.config.MqttGateway;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class MqttClientTest {
@Autowired
private MqttGateway mqttGateway;
public void sendMsg() {
mqttGateway.sendMsgToMqtt("worker/location/1", "hello mqtt spring boot");
log.info("message is send");
mqttGateway.sendMsgToMqtt("worker/alert/2", "hello mqtt spring boot2");
log.info("message is send2");
}
}

View File

@ -0,0 +1,25 @@
package com.fuyuanshen.modules.mqtt.publish;
import com.fuyuanshen.modules.mqtt.config.MqttGateway;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Service;
/**
* @Author: HarryLin
* @Date: 2025/3/20 16:16
* @Company: 北京红山信息科技研究院有限公司
* @Email: linyun@***.com.cn
**/
@Service
public class MqttMessageSender {
@Autowired
private MqttGateway mqttGateway;
public void sendMsg(@Header(value = MqttHeaders.TOPIC) String topic, String payload) {
mqttGateway.sendMsgToMqtt(topic,payload);
}
public void sendMsg(@Header(value = MqttHeaders.TOPIC) String topic, @Header(value = MqttHeaders.QOS) int qos, String payload) {
mqttGateway.sendMsgToMqtt(topic,qos,payload);
}
}

View File

@ -0,0 +1,31 @@
package com.fuyuanshen.modules.mqtt.receiver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.MessagingException;
import org.springframework.stereotype.Service;
import java.util.Objects;
/**
* @Author: HarryLin
* @Date: 2025/3/20 15:24
* @Company: 北京红山信息科技研究院有限公司
* @Email: linyun@***.com.cn
**/
@Service
@Slf4j
public class ReceiverMessageHandler implements MessageHandler {
@Override
public void handleMessage(Message<?> message) throws MessagingException{
Object payload = message.getPayload();
MessageHeaders headers = message.getHeaders();
String receivedTopic = Objects.requireNonNull(headers.get("mqtt_receivedTopic")).toString();
String receivedQos = Objects.requireNonNull(headers.get("mqtt_receivedQos")).toString();
String timestamp = Objects.requireNonNull(headers.get("timestamp")).toString();
log.info("MQTT payload= {} \n receivedTopic = {} \n receivedQos = {} \n timestamp = {}"
,payload,receivedTopic,receivedQos,timestamp);
}
}

View File

@ -0,0 +1,25 @@
package com.fuyuanshen.modules.security.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class DeviceDataService {
@ServiceActivator(inputChannel = "mqttInputChannel")
public void handleDeviceData(Message<?> message) {
String topic = message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC).toString();
String payload = message.getPayload().toString();
// 解析设备数据
if (topic.startsWith("device/data/")) {
log.info("Received device data device/data/: {} {}", topic, payload);
}
}
}

View File

@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import com.fuyuanshen.base.BaseEntity; import com.fuyuanshen.base.BaseEntity;
@ -21,7 +20,6 @@ import java.io.Serializable;
**/ **/
@Data @Data
@TableName("device") @TableName("device")
@JsonInclude(JsonInclude.Include.ALWAYS) // 关键注解
public class Device extends BaseEntity implements Serializable { public class Device extends BaseEntity implements Serializable {
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.AUTO)

View File

@ -17,9 +17,6 @@ public class DeviceForm {
@ApiModelProperty(value = "ID", hidden = true) @ApiModelProperty(value = "ID", hidden = true)
private Long id; private Long id;
@ApiModelProperty(value = "设备记录ID")
private Long assignId;
@ApiModelProperty(value = "设备类型") @ApiModelProperty(value = "设备类型")
private Long deviceType; private Long deviceType;

View File

@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;

View File

@ -5,7 +5,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fuyuanshen.modules.system.domain.app.APPDeviceType; import com.fuyuanshen.modules.system.domain.app.APPDeviceType;
import com.fuyuanshen.modules.system.domain.dto.DeviceQueryCriteria; import com.fuyuanshen.modules.system.domain.dto.DeviceQueryCriteria;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
@ -24,6 +23,6 @@ public interface AppDeviceTypeMapper extends BaseMapper<APPDeviceType> {
* @param criteria 查询条件 * @param criteria 查询条件
* @return 设备类型列表 * @return 设备类型列表
*/ */
List<APPDeviceType> appTypeList(@Param("criteria")DeviceQueryCriteria criteria); List<APPDeviceType> appTypeList(DeviceQueryCriteria criteria);
} }

View File

@ -146,20 +146,6 @@ public class DeviceController {
} }
@Log("撤回设备")
@ApiOperation("撤回设备")
@PostMapping(value = "/withdraw")
public ResponseVO<Object> withdrawDevice(@Validated @ModelAttribute DeviceForm deviceForm) {
try {
deviceService.withdrawDevice(deviceForm);
} catch (Exception e) {
log.error("updateDevice error: " + e.getMessage());
return ResponseVO.fail("出错了");
}
return ResponseVO.success(null);
}
@ApiOperation("设备详情") @ApiOperation("设备详情")
@GetMapping(value = "/detail/{id}") @GetMapping(value = "/detail/{id}")
public ResponseVO<Object> getDevice(@PathVariable Long id) { public ResponseVO<Object> getDevice(@PathVariable Long id) {

View File

@ -1,20 +1,56 @@
package com.fuyuanshen.modules.system.rest.app; package com.fuyuanshen.modules.system.rest.app;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fuyuanshen.annotation.Log;
import com.fuyuanshen.exception.BadRequestException;
import com.fuyuanshen.modules.system.constant.UserConstants;
import com.fuyuanshen.modules.system.domain.Device;
import com.fuyuanshen.modules.system.domain.User;
import com.fuyuanshen.modules.system.domain.app.APPDevice; import com.fuyuanshen.modules.system.domain.app.APPDevice;
import com.fuyuanshen.modules.system.domain.app.APPDeviceType; import com.fuyuanshen.modules.system.domain.app.APPDeviceType;
import com.fuyuanshen.modules.system.domain.dto.CustomerVo;
import com.fuyuanshen.modules.system.domain.dto.DeviceExcelImportDTO;
import com.fuyuanshen.modules.system.domain.dto.DeviceForm;
import com.fuyuanshen.modules.system.domain.dto.DeviceQueryCriteria; import com.fuyuanshen.modules.system.domain.dto.DeviceQueryCriteria;
import com.fuyuanshen.modules.system.domain.dto.app.APPUnbindDTO; import com.fuyuanshen.modules.system.domain.dto.app.APPUnbindDTO;
import com.fuyuanshen.modules.system.listener.excel.DeviceImportParams;
import com.fuyuanshen.modules.system.listener.excel.UploadDeviceDataListener;
import com.fuyuanshen.modules.system.mapper.DeviceMapper;
import com.fuyuanshen.modules.system.mapper.DeviceTypeMapper;
import com.fuyuanshen.modules.system.mapper.UserMapper;
import com.fuyuanshen.modules.system.service.DeviceService;
import com.fuyuanshen.modules.system.service.UserService;
import com.fuyuanshen.modules.system.service.app.APPDeviceService; import com.fuyuanshen.modules.system.service.app.APPDeviceService;
import com.fuyuanshen.modules.system.service.impl.DeviceExportService;
import com.fuyuanshen.modules.utils.ResponseVO; import com.fuyuanshen.modules.utils.ResponseVO;
import com.fuyuanshen.modules.utils.excel.ImportResult;
import com.fuyuanshen.utils.FileUtil;
import com.fuyuanshen.utils.PageResult; import com.fuyuanshen.utils.PageResult;
import com.fuyuanshen.utils.SecurityUtils;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.List; import java.util.List;
/** /**
@ -50,7 +86,7 @@ public class APPDeviceController {
@PostMapping(value = "/typeList") @PostMapping(value = "/typeList")
@ApiOperation("APP用户设备类型列表") @ApiOperation("APP用户设备类型列表")
public ResponseVO<List<APPDeviceType>> appTypeList(@RequestBody DeviceQueryCriteria criteria) { public ResponseVO<List<APPDeviceType>> appTypeList(@RequestBody DeviceQueryCriteria criteria) {
List<APPDeviceType> typeList = appDeviceService.appTypeList(criteria); List<APPDeviceType> typeList = appDeviceService.appTypeList(criteria);
return ResponseVO.success(typeList); return ResponseVO.success(typeList);
} }

View File

@ -134,5 +134,4 @@ public class APPUserController {
// appUserService.sendSms(phoneNumber); // appUserService.sendSms(phoneNumber);
return ResponseVO.success("success"); return ResponseVO.success("success");
} }
} }

View File

@ -73,8 +73,6 @@ public interface DeviceService extends IService<Device> {
*/ */
void assignCustomer(CustomerVo customerVo); void assignCustomer(CustomerVo customerVo);
void withdrawDevice(DeviceForm deviceForm);
/** /**
* 多选删除 * 多选删除
* *
@ -112,4 +110,5 @@ public interface DeviceService extends IService<Device> {
*/ */
void unbindDevice(DeviceForm deviceForm); void unbindDevice(DeviceForm deviceForm);
} }

View File

@ -56,12 +56,10 @@ public class APPDeviceServiceImpl extends ServiceImpl<APPDeviceMapper, APPDevice
*/ */
@Override @Override
public PageResult<APPDevice> appDeviceList(Page<APPDevice> page, DeviceQueryCriteria criteria) { public PageResult<APPDevice> appDeviceList(Page<APPDevice> page, DeviceQueryCriteria criteria) {
criteria.setCustomerId(SecurityUtils.getCurrentUserId());
IPage<APPDevice> devices = appDeviceMapper.appDeviceList(page, criteria); IPage<APPDevice> devices = appDeviceMapper.appDeviceList(page, criteria);
return new PageResult<>(devices.getRecords(), devices.getTotal()); return new PageResult<>(devices.getRecords(), devices.getTotal());
} }
/** /**
* APP用户设备类型列表 * APP用户设备类型列表
* *
@ -70,8 +68,7 @@ public class APPDeviceServiceImpl extends ServiceImpl<APPDeviceMapper, APPDevice
*/ */
@Override @Override
public List<APPDeviceType> appTypeList(DeviceQueryCriteria criteria) { public List<APPDeviceType> appTypeList(DeviceQueryCriteria criteria) {
criteria.setCustomerId(SecurityUtils.getCurrentUserId()); return appDeviceTypeMapper.appTypeList(criteria);
return appDeviceTypeMapper.appTypeList(criteria);
} }
@ -111,9 +108,6 @@ public class APPDeviceServiceImpl extends ServiceImpl<APPDeviceMapper, APPDevice
} }
Device device = devices.get(0); Device device = devices.get(0);
device.setBindingStatus(BindingStatusEnum.BOUND.getCode());
deviceMapper.updateById( device);
APPDevice appDevice = new APPDevice(); APPDevice appDevice = new APPDevice();
BeanUtil.copyProperties(device, appDevice); BeanUtil.copyProperties(device, appDevice);
appDevice.setBindingType(UserType.APP.getValue()); appDevice.setBindingType(UserType.APP.getValue());
@ -130,7 +124,6 @@ public class APPDeviceServiceImpl extends ServiceImpl<APPDeviceMapper, APPDevice
DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType()); DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType());
APPDeviceType type = new APPDeviceType(); APPDeviceType type = new APPDeviceType();
BeanUtil.copyProperties(deviceType, type); BeanUtil.copyProperties(deviceType, type);
type.setCustomerId(currentUserId);
appDeviceTypeMapper.insert(type); appDeviceTypeMapper.insert(type);
} }

View File

@ -456,30 +456,6 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
} }
/**
* 撤回设备
*
* @param deviceForm
*/
@Override
public void withdrawDevice(DeviceForm deviceForm) {
DeviceAssignments assignment = deviceAssignmentsMapper.selectById(deviceForm.getAssignId());
// 接收者
assignment.setAssigneeName("");
deviceAssignmentsMapper.updateById(assignment);
LambdaQueryWrapper<DeviceAssignments> q1 = new LambdaQueryWrapper<>();
q1.eq(DeviceAssignments::getAssignerId, assignment.getAssigneeId())
.like(DeviceAssignments::getLever, assignment.getLever())
.ne(DeviceAssignments::getId, assignment.getId());
DeviceAssignments d1 = new DeviceAssignments();
d1.setActive(DeviceActiveStatusEnum.INACTIVE.getCode());
deviceAssignmentsMapper.update(d1, q1);
}
/** /**
* 创建并保存设备类型授权记录 * 创建并保存设备类型授权记录
* *
@ -575,7 +551,6 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
* @param ids * @param ids
*/ */
@Override @Override
@Transactional(rollbackFor = Exception.class)
public void deleteAssign(List<Long> ids) { public void deleteAssign(List<Long> ids) {
// Step 1: 查询所有传入的设备(根据 ID // Step 1: 查询所有传入的设备(根据 ID
List<DeviceAssignments> deviceAssignments = deviceAssignmentsMapper.selectBatchIds(ids); List<DeviceAssignments> deviceAssignments = deviceAssignmentsMapper.selectBatchIds(ids);
@ -587,8 +562,7 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
throw new BadRequestException("已分配的设备不允许删除!!!"); throw new BadRequestException("已分配的设备不允许删除!!!");
} }
deviceAssignmentsMapper.deleteBatchIds(nonNullCustomerIds); deviceAssignmentsMapper.deleteBatchIds(ids);
deviceTypeGrantsMapper.delete(new QueryWrapper<DeviceTypeGrants>().in("assignment_id", nonNullCustomerIds));
} }

View File

@ -1,13 +1,9 @@
package com.fuyuanshen.modules.system.service.impl; package com.fuyuanshen.modules.system.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fuyuanshen.exception.BadRequestException;
import com.fuyuanshen.modules.system.domain.Device;
import com.fuyuanshen.modules.system.domain.DeviceTypeGrants; import com.fuyuanshen.modules.system.domain.DeviceTypeGrants;
import com.fuyuanshen.modules.system.mapper.DeviceMapper;
import com.fuyuanshen.modules.system.mapper.DeviceTypeGrantsMapper; import com.fuyuanshen.modules.system.mapper.DeviceTypeGrantsMapper;
import com.fuyuanshen.modules.utils.NanoId; import com.fuyuanshen.modules.utils.NanoId;
import com.fuyuanshen.utils.enums.NanoIdLengthEnum; import com.fuyuanshen.utils.enums.NanoIdLengthEnum;
@ -45,7 +41,6 @@ import java.util.stream.Collectors;
public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceType> implements DeviceTypeService { public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceType> implements DeviceTypeService {
private final DeviceTypeMapper deviceTypeMapper; private final DeviceTypeMapper deviceTypeMapper;
private final DeviceMapper deviceMapper;
private final UserMapper userMapper; private final UserMapper userMapper;
private final UserCacheManager userCacheManager; private final UserCacheManager userCacheManager;
private final DeviceTypeGrantsMapper deviceTypeGrantsMapper; private final DeviceTypeGrantsMapper deviceTypeGrantsMapper;
@ -147,20 +142,9 @@ public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceT
} }
/**
* 修改设备类型
*
* @param resources /
*/
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void update(DeviceType resources) { public void update(DeviceType resources) {
List<Device> deviceList = deviceMapper.selectList(new QueryWrapper<Device>().eq("device_type", resources.getId()));
if (CollectionUtil.isNotEmpty(deviceList)) {
throw new BadRequestException("该设备类型下已有设备,请先解绑设备!!!");
}
DeviceType deviceType = getById(resources.getId()); DeviceType deviceType = getById(resources.getId());
deviceType.copy(resources); deviceType.copy(resources);
Timestamp timestamp = new Timestamp(System.currentTimeMillis()); Timestamp timestamp = new Timestamp(System.currentTimeMillis());
@ -169,32 +153,10 @@ public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceT
} }
/**
* 删除设备类型
*
* @param ids /
*/
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void deleteAll(List<Long> ids) { public void deleteAll(List<Long> ids) {
// 查询所有与 device 关联的 deviceType IDs deviceTypeMapper.deleteBatchIds(ids);
List<Device> deviceList = deviceMapper.selectList(new QueryWrapper<Device>().in("device_type", ids));
// 提取与 device 关联的 deviceType IDs
List<Long> filteredIds = deviceList.stream()
.map(Device::getDeviceType)
.distinct()
.collect(Collectors.toList());
// 从原始 ids 中移除已关联 device 的 id即过滤掉能查到结果的 id
List<Long> idsToBeDeleted = ids.stream()
.filter(id -> !filteredIds.contains(id))
.collect(Collectors.toList());
if (idsToBeDeleted.isEmpty()) {
throw new BadRequestException("选中设备类型已绑定设备,请先解绑设备!!!");
}
// 删除过滤后的 id 列表
deviceTypeMapper.deleteBatchIds(idsToBeDeleted);
deviceTypeGrantsMapper.delete(new QueryWrapper<DeviceTypeGrants>().in("device_type_id", idsToBeDeleted));
} }

View File

@ -4,9 +4,9 @@ spring:
druid: druid:
db-type: com.alibaba.druid.pool.DruidDataSource db-type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.p6spy.engine.spy.P6SpyDriver driverClassName: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:p6spy:mysql://192.168.2.23:3306/eladmin?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false url: jdbc:p6spy:mysql://120.79.224.186:3366/eladmin?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
username: root username: root
password: root password: 1fys@QWER..
# 初始连接数,建议设置为与最小空闲连接数相同 # 初始连接数,建议设置为与最小空闲连接数相同
initial-size: 20 initial-size: 20
# 最小空闲连接数,保持足够的空闲连接以应对请求 # 最小空闲连接数,保持足够的空闲连接以应对请求
@ -53,10 +53,10 @@ spring:
redis: redis:
#数据库索引 #数据库索引
database: ${REDIS_DB:2} database: ${REDIS_DB:0}
host: ${REDIS_HOST:123.207.99.140} host: ${REDIS_HOST:120.79.224.186}
port: ${REDIS_PORT:6379} port: ${REDIS_PORT:26379}
password: ${REDIS_PWD:ccxx11234} password: ${REDIS_PWD:1fys@QWER..}
#连接超时时间 #连接超时时间
timeout: 5000 timeout: 5000
# 连接池配置 # 连接池配置
@ -149,3 +149,12 @@ file:
logging: logging:
level: level:
com.fuyuanshen: debug com.fuyuanshen: debug
# MQTT配置
mqtt:
username: admin
password: fys123456
url: tcp://127.0.0.1:1883
subClientId: wuLang_subClient_01
subTopic: worker/alert/#,worker/location/#
pubTopic: worker/location
pubClientId: wuLang_pubClient_01

View File

@ -44,7 +44,7 @@ spring:
max-file-size: 5MB # 设置单个上传文件的最大大小为10MB max-file-size: 5MB # 设置单个上传文件的最大大小为10MB
max-request-size: 5MB max-request-size: 5MB
jackson: jackson:
default-property-inclusion: always default-property-inclusion: non_null
# pid: # pid:
# file: /自行指定位置/eladmin.pid # file: /自行指定位置/eladmin.pid

View File

@ -19,8 +19,7 @@
</resultMap> </resultMap>
<sql id="Base_Column_List"> <sql id="Base_Column_List">
id id,type_name,is_support_ble,locate_mode,network_way,create_by,
,type_name,is_support_ble,locate_mode,network_way,create_by,
update_by,create_time,update_time,customer_id,communication_mode update_by,create_time,update_time,customer_id,communication_mode
</sql> </sql>
@ -28,6 +27,31 @@
<select id="appTypeList" resultType="com.fuyuanshen.modules.system.domain.app.APPDeviceType"> <select id="appTypeList" resultType="com.fuyuanshen.modules.system.domain.app.APPDeviceType">
select d.* from app_device_type as d select d.* from app_device_type as d
<where> <where>
<!-- 时间范围等其他条件保持原样 -->
<if test="criteria.deviceName != null and criteria.deviceName.trim() != ''">
and d.device_name like concat('%', TRIM(#{criteria.deviceName}), '%')
</if>
<if test="criteria.deviceMac != null and criteria.deviceMac.trim() != ''">
and d.device_mac = #{criteria.deviceMac}
</if>
<if test="criteria.deviceImei != null and criteria.deviceImei.trim() != ''">
and d.device_imei = #{criteria.deviceImei}
</if>
<if test="criteria.deviceSn != null">
and d.device_sn = #{criteria.deviceSn}
</if>
<if test="criteria.deviceType != null">
and d.device_type = #{criteria.deviceType}
</if>
<if test="criteria.deviceStatus != null">
and d.device_status = #{criteria.deviceStatus}
</if>
<if test="criteria.createTime != null and criteria.createTime.size() != 0">
and d.create_time between #{criteria.createTime[0]} and #{criteria.createTime[1]}
</if>
<if test="criteria.tenantId != null">
AND tenant_id = #{criteria.tenantId}
</if>
and d.customer_id = #{criteria.customerId} and d.customer_id = #{criteria.customerId}
</where> </where>
order by d.create_time desc order by d.create_time desc

View File

@ -61,6 +61,6 @@
and dt.create_by = #{criteria.createBy} and dt.create_by = #{criteria.createBy}
</if> </if>
</where> </where>
ORDER BY create_time DESC order by create_time desc
</select> </select>
</mapper> </mapper>

View File

@ -223,6 +223,14 @@
<artifactId>commons-text</artifactId> <artifactId>commons-text</artifactId>
<version>1.13.0</version> <version>1.13.0</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-mqtt</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>