diff --git a/ems-admin/src/main/java/com/xzzn/web/controller/ems/EmsPointMatchController.java b/ems-admin/src/main/java/com/xzzn/web/controller/ems/EmsPointMatchController.java index ad98c35..75b1ca9 100644 --- a/ems-admin/src/main/java/com/xzzn/web/controller/ems/EmsPointMatchController.java +++ b/ems-admin/src/main/java/com/xzzn/web/controller/ems/EmsPointMatchController.java @@ -2,10 +2,13 @@ package com.xzzn.web.controller.ems; import java.util.List; import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import org.apache.commons.collections4.CollectionUtils; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.xzzn.common.annotation.Log; @@ -13,6 +16,8 @@ import com.xzzn.common.core.controller.BaseController; import com.xzzn.common.core.domain.AjaxResult; import com.xzzn.common.enums.BusinessType; import com.xzzn.ems.domain.EmsPointMatch; +import com.xzzn.ems.domain.vo.DevicePointMatchVo; +import com.xzzn.ems.domain.vo.ImportPointDataRequest; import com.xzzn.ems.service.IEmsPointMatchService; import com.xzzn.common.utils.poi.ExcelUtil; import org.springframework.web.multipart.MultipartFile; @@ -62,4 +67,21 @@ public class EmsPointMatchController extends BaseController return success(message); } + /** + * 上传设备的点位清单 + * @param request + * @return + * @throws Exception + */ + @PreAuthorize("@ss.hasPermi('system:user:import')") + @Log(title = "点位匹配", businessType = BusinessType.IMPORT) + @PostMapping("/importDataByDevice") + public void importDataByDevice(@Valid ImportPointDataRequest request, HttpServletResponse response) { + List list = emsPointMatchService.importDataByDevice(request, getUsername()); + if (CollectionUtils.isNotEmpty(list)) { + ExcelUtil util = new ExcelUtil<>(DevicePointMatchVo.class); + util.exportExcel(response, list, "点位匹配数据"); + } + } + } diff --git a/ems-common/src/main/java/com/xzzn/common/constant/RedisKeyConstants.java b/ems-common/src/main/java/com/xzzn/common/constant/RedisKeyConstants.java index 8d080d8..dc83d4f 100644 --- a/ems-common/src/main/java/com/xzzn/common/constant/RedisKeyConstants.java +++ b/ems-common/src/main/java/com/xzzn/common/constant/RedisKeyConstants.java @@ -62,6 +62,11 @@ public class RedisKeyConstants */ public static final String COOLING = "COOLING_"; + /** + * 点位匹配数据 redis key + */ + public static final String POINT_MATCH = "POINT_MATCH_"; + /** * 存放单个设备同步过来的原始数据-最晚一次数据 */ diff --git a/ems-system/src/main/java/com/xzzn/ems/domain/EmsPointMatch.java b/ems-system/src/main/java/com/xzzn/ems/domain/EmsPointMatch.java index 9bc8f12..1abe5e0 100644 --- a/ems-system/src/main/java/com/xzzn/ems/domain/EmsPointMatch.java +++ b/ems-system/src/main/java/com/xzzn/ems/domain/EmsPointMatch.java @@ -70,6 +70,10 @@ public class EmsPointMatch extends BaseEntity @Excel(name = "点位是否需要区分多设备:0-不需要 1-需要") private Long needDiffDeviceId; + /** 设备唯一标识符 */ + @Excel(name = "设备唯一标识符") + private String deviceId; + public void setId(Long id) { this.id = id; @@ -208,6 +212,14 @@ public class EmsPointMatch extends BaseEntity return needDiffDeviceId; } + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) @@ -230,6 +242,7 @@ public class EmsPointMatch extends BaseEntity .append("updateBy", getUpdateBy()) .append("updateTime", getUpdateTime()) .append("remark", getRemark()) + .append("deviceId", getDeviceId()) .toString(); } } diff --git a/ems-system/src/main/java/com/xzzn/ems/domain/vo/DevicePointMatchVo.java b/ems-system/src/main/java/com/xzzn/ems/domain/vo/DevicePointMatchVo.java new file mode 100644 index 0000000..d8903d7 --- /dev/null +++ b/ems-system/src/main/java/com/xzzn/ems/domain/vo/DevicePointMatchVo.java @@ -0,0 +1,96 @@ +package com.xzzn.ems.domain.vo; + +import com.xzzn.common.annotation.Excel; + +import java.io.Serializable; + +/** + * 点位清单上传参数 + */ +public class DevicePointMatchVo implements Serializable { + private static final long serialVersionUID = 1L; + + /** 点位匹配字段 */ + @Excel(name = "点位匹配字段") + private String matchField; + + /** 数据点位 */ + @Excel(name = "数据点位") + private String dataPoint; + + /** 数据点位名称 */ + @Excel(name = "数据点位名称") + private String dataPointName; + + /** 数据单位 */ + @Excel(name = "数据单位") + private String dataUnit; +// +// /** 数据点位来源设备 */ +// @Excel(name = "数据点位来源设备") +// private String dataDevice; + + /** 寄存器地址 */ + @Excel(name = "寄存器地址") + private String ipAddress; + + /** 错误信息 */ + @Excel(name = "错误信息") + private String errorMsg; + + public String getMatchField() { + return matchField; + } + + public void setMatchField(String matchField) { + this.matchField = matchField; + } + + public String getDataPoint() { + return dataPoint; + } + + public void setDataPoint(String dataPoint) { + this.dataPoint = dataPoint; + } + + public String getDataPointName() { + return dataPointName; + } + + public void setDataPointName(String dataPointName) { + this.dataPointName = dataPointName; + } + + public String getDataUnit() { + return dataUnit; + } + + public void setDataUnit(String dataUnit) { + this.dataUnit = dataUnit; + } + +// public String getDataDevice() { +// return dataDevice; +// } +// +// public void setDataDevice(String dataDevice) { +// this.dataDevice = dataDevice; +// } + + public String getIpAddress() { + return ipAddress; + } + + public void setIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + } + + public String getErrorMsg() { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) { + this.errorMsg = errorMsg; + } +} diff --git a/ems-system/src/main/java/com/xzzn/ems/domain/vo/ImportPointDataRequest.java b/ems-system/src/main/java/com/xzzn/ems/domain/vo/ImportPointDataRequest.java new file mode 100644 index 0000000..d5a6416 --- /dev/null +++ b/ems-system/src/main/java/com/xzzn/ems/domain/vo/ImportPointDataRequest.java @@ -0,0 +1,61 @@ +package com.xzzn.ems.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.util.Date; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import org.springframework.web.multipart.MultipartFile; + +/** + * 上传设备点位清单请求参数 + */ +public class ImportPointDataRequest { + + /** 站点id */ + @NotBlank(message = "站点ID不能为空") + private String siteId; + /** 设备id */ + @NotBlank(message = "设备ID不能为空") + private String deviceId; + /** 设备类型 */ + @NotBlank(message = "设备类型不能为空") + private String deviceCategory; + /** 上传点位清单文件 */ + @NotNull(message = "点位清单文件不能为空") + private MultipartFile file; + + public String getSiteId() { + return siteId; + } + + public void setSiteId(String siteId) { + this.siteId = siteId; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getDeviceCategory() { + return deviceCategory; + } + + public void setDeviceCategory(String deviceCategory) { + this.deviceCategory = deviceCategory; + } + + public MultipartFile getFile() { + return file; + } + + public void setFile(MultipartFile file) { + this.file = file; + } +} diff --git a/ems-system/src/main/java/com/xzzn/ems/enums/DeviceMatchTable.java b/ems-system/src/main/java/com/xzzn/ems/enums/DeviceMatchTable.java new file mode 100644 index 0000000..5a9c59d --- /dev/null +++ b/ems-system/src/main/java/com/xzzn/ems/enums/DeviceMatchTable.java @@ -0,0 +1,82 @@ +package com.xzzn.ems.enums; + +import com.xzzn.ems.domain.EmsAmmeterData; +import com.xzzn.ems.domain.EmsBatteryCluster; +import com.xzzn.ems.domain.EmsBatteryData; +import com.xzzn.ems.domain.EmsBatteryGroup; +import com.xzzn.ems.domain.EmsBatteryStack; +import com.xzzn.ems.domain.EmsCoolingData; +import com.xzzn.ems.domain.EmsPcsBranchData; +import com.xzzn.ems.domain.EmsPcsData; +import com.xzzn.ems.domain.EmsXfData; + +import java.util.HashMap; +import java.util.Map; + +/** + * 设备匹配表枚举类 + */ +public enum DeviceMatchTable +{ + PCS("PCS", "ems_pcs_data", EmsPcsData.class), + BRANCH("BRANCH", "ems_pcs_branch_data", EmsPcsBranchData.class), + STACK("STACK", "ems_battery_stack", EmsBatteryStack.class), + CLUSTER("CLUSTER", "ems_battery_cluster", EmsBatteryCluster.class), + BATTERY("BATTERY", "ems_battery_data", EmsBatteryData.class), + AMMETER("AMMETER", "ems_ammeter_data", EmsAmmeterData.class), + COOLING("COOLING", "ems_cooling_data", EmsCoolingData.class), + DH("DH", "ems_dh_data", EmsBatteryData.class), + XF("XF", "ems_xf_data", EmsXfData.class), + BATTERY_GROUP("BATTERY_GROUP", "ems_battery_group", EmsBatteryGroup.class); + + private final String code; + private final String matchTable; + + private final Class matchTableClass; + + DeviceMatchTable(String code, String matchTable, Class matchTableClass) + { + this.code = code; + this.matchTable = matchTable; + this.matchTableClass = matchTableClass; + } + + public String getCode() + { + return code; + } + + public String getMatchTable() { + return matchTable; + } + + public Class getMatchTableClass() { + return matchTableClass; + } + + // 缓存code与matchTable的映射(优化查询效率) + private static final Map DEVICE_MATCH_TABLE_MAP = new HashMap<>(); + + // 缓存table与实体类的映射(优化查询效率) + private static final Map> TABLE_TO_CLASS_MAP = new HashMap<>(); + + // 静态块初始化缓存 + static { + for (DeviceMatchTable category : DeviceMatchTable.values()) { + DEVICE_MATCH_TABLE_MAP.put(category.code, category.matchTable); + TABLE_TO_CLASS_MAP.put(category.matchTable, category.matchTableClass); + } + } + + + // 通过code获取matchTable的方法 + public static String getMatchTableByCode(String code) { + return DEVICE_MATCH_TABLE_MAP.get(code); // 从缓存中直接获取,效率高 + } + + // 通过table获取实体类的方法 + public static Class getClassByTable(String matchTable) { + return TABLE_TO_CLASS_MAP.get(matchTable); // 从缓存中直接获取,效率高 + } + +} diff --git a/ems-system/src/main/java/com/xzzn/ems/mapper/EmsPointMatchMapper.java b/ems-system/src/main/java/com/xzzn/ems/mapper/EmsPointMatchMapper.java index 19a1f29..433589f 100644 --- a/ems-system/src/main/java/com/xzzn/ems/mapper/EmsPointMatchMapper.java +++ b/ems-system/src/main/java/com/xzzn/ems/mapper/EmsPointMatchMapper.java @@ -140,4 +140,8 @@ public interface EmsPointMatchMapper // 根据站点,设备类别,点位,获取唯一数据 public EmsPointMatch getUniquePoint(@Param("siteId")String siteId, @Param("deviceCategory")String deviceCategory, @Param("dataPoint")String dataPoint); + + EmsPointMatch getOnePointMatch(@Param("siteId") String siteId, @Param("deviceId") String deviceId, @Param("deviceCategory") String deviceCategory, @Param("dataPoint") String dataPoint); + + List getDevicePointMatchList(@Param("siteId") String siteId, @Param("deviceId") String deviceId, @Param("deviceCategory") String deviceCategory); } diff --git a/ems-system/src/main/java/com/xzzn/ems/service/IEmsPointMatchService.java b/ems-system/src/main/java/com/xzzn/ems/service/IEmsPointMatchService.java index 2242e4e..c9027ac 100644 --- a/ems-system/src/main/java/com/xzzn/ems/service/IEmsPointMatchService.java +++ b/ems-system/src/main/java/com/xzzn/ems/service/IEmsPointMatchService.java @@ -3,6 +3,8 @@ package com.xzzn.ems.service; import java.util.List; import com.xzzn.ems.domain.EmsPointMatch; +import com.xzzn.ems.domain.vo.DevicePointMatchVo; +import com.xzzn.ems.domain.vo.ImportPointDataRequest; /** * 点位匹配Service接口 @@ -29,4 +31,6 @@ public interface IEmsPointMatchService * @return */ public String importPoint(List userList, boolean updateSupport, String operName); + + public List importDataByDevice(ImportPointDataRequest request, String operName); } diff --git a/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsPointMatchServiceImpl.java b/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsPointMatchServiceImpl.java index 25942cb..d3c3ff7 100644 --- a/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsPointMatchServiceImpl.java +++ b/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsPointMatchServiceImpl.java @@ -1,15 +1,33 @@ package com.xzzn.ems.service.impl; +import java.io.IOException; +import java.util.ArrayList; import java.util.List; +import com.alibaba.fastjson2.JSON; +import com.xzzn.common.constant.RedisKeyConstants; +import com.xzzn.common.core.redis.RedisCache; import com.xzzn.common.exception.ServiceException; import com.xzzn.common.utils.StringUtils; import com.xzzn.common.utils.bean.BeanValidators; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.web.multipart.MultipartFile; + +import com.xzzn.common.utils.poi.ExcelUtil; +import com.xzzn.ems.domain.vo.DevicePointMatchVo; +import com.xzzn.ems.domain.vo.ImportPointDataRequest; +import com.xzzn.ems.enums.DeviceMatchTable; import com.xzzn.ems.mapper.EmsPointMatchMapper; import com.xzzn.ems.domain.EmsPointMatch; import com.xzzn.ems.service.IEmsPointMatchService; +import com.xzzn.ems.utils.MatchTableUtils; import javax.validation.Validator; @@ -22,10 +40,13 @@ import javax.validation.Validator; @Service public class EmsPointMatchServiceImpl implements IEmsPointMatchService { + private static final Logger log = LoggerFactory.getLogger(EmsPointMatchServiceImpl.class); @Autowired private EmsPointMatchMapper emsPointMatchMapper; @Autowired protected Validator validator; + @Autowired + private RedisCache redisCache; /** * 查询点位匹配列表 @@ -92,5 +113,89 @@ public class EmsPointMatchServiceImpl implements IEmsPointMatchService return successMsg.toString(); } + @Override + @Transactional(rollbackFor = Exception.class) + public List importDataByDevice(ImportPointDataRequest request, String operName) { + ExcelUtil util = new ExcelUtil<>(DevicePointMatchVo.class); + List pointMatchList = new ArrayList<>(); + MultipartFile file = request.getFile(); + if (file.isEmpty()) { + throw new ServiceException("点位清单文件不能为空"); + } + try { + pointMatchList = util.importExcel(file.getInputStream()); + } catch (IOException e) { + log.info("点位清单导入失败:{}", e.getMessage()); + throw new ServiceException("点位清单导入失败!"); + } + if (CollectionUtils.isEmpty(pointMatchList)) { + throw new ServiceException("导入用户数据不能为空!"); + } + String siteId = request.getSiteId(); + String deviceId = request.getDeviceId(); + String deviceCategory = request.getDeviceCategory(); + List errorList = new ArrayList<>(); + for (DevicePointMatchVo pointMatch : pointMatchList) { + try { + //校验点位清单文件内容 + if (validDevicePointMatch(pointMatch, errorList)) { + continue; + } + EmsPointMatch savePoint = new EmsPointMatch(); + BeanUtils.copyProperties(pointMatch, savePoint); + savePoint.setSiteId(siteId); + savePoint.setDeviceId(deviceId); + savePoint.setDeviceCategory(deviceCategory); + savePoint.setMatchTable(DeviceMatchTable.getMatchTableByCode(deviceCategory)); + savePoint.setPointName(MatchTableUtils.getFieldAnnotation(DeviceMatchTable.getClassByTable(savePoint.getMatchTable()), StringUtils.toCamelCase(savePoint.getMatchField()))); + savePoint.setCreateBy(operName); + savePoint.setUpdateBy(operName); + // 验证点位是否存在 + EmsPointMatch dbPoint = emsPointMatchMapper.getOnePointMatch(siteId, deviceId, deviceCategory, pointMatch.getDataPoint()); + if (StringUtils.isNull(dbPoint)) { + emsPointMatchMapper.insertEmsPointMatch(savePoint); + } else { + emsPointMatchMapper.updateEmsPointMatch(savePoint); + } + } catch (Exception e) { + log.info("点位清单导入失败:{}", e.getMessage()); + throw new ServiceException("点位清单导入失败!"); + } + } + // 同步到Redis + syncToRedis(siteId, deviceId, deviceCategory); + return errorList; + } + + private boolean validDevicePointMatch(DevicePointMatchVo pointMatch, List errorList) { + StringBuilder errorMsg = new StringBuilder(); + if (StringUtils.isBlank(pointMatch.getMatchField())) { + errorMsg.append("点位匹配字段不能为空;"); + } + if (StringUtils.isBlank(pointMatch.getDataPoint())) { + errorMsg.append("数据点位不能为空;"); + } + if (StringUtils.isBlank(pointMatch.getDataPointName())) { + errorMsg.append("数据点位名称不能为空;"); + } +// if (StringUtils.isBlank(pointMatch.getDataDevice())) { +// errorMsg.append("数据点位来源设备不能为空;"); +// } + if (errorMsg.length() > 0) { + pointMatch.setErrorMsg(errorMsg.toString()); + errorList.add(pointMatch); + return true; + } + return false; + } + + private void syncToRedis(String siteId, String deviceId, String deviceCategory) { + // 同步到Redis + String pointMatchKey = RedisKeyConstants.POINT_MATCH + deviceCategory + "_" + siteId + "_" + deviceId; + List pointMatchData = emsPointMatchMapper.getDevicePointMatchList(siteId, deviceId, deviceCategory); +// log.info("同步点位匹配数据到Redis key:{} data:{}", pointMatchKey, pointMatchData); + redisCache.setCacheObject(pointMatchKey, pointMatchData); + log.info("点位匹配数据同步完成 data:{}", JSON.toJSONString(redisCache.getCacheObject(pointMatchKey))); + } } diff --git a/ems-system/src/main/java/com/xzzn/ems/utils/MatchTableUtils.java b/ems-system/src/main/java/com/xzzn/ems/utils/MatchTableUtils.java new file mode 100644 index 0000000..49649f6 --- /dev/null +++ b/ems-system/src/main/java/com/xzzn/ems/utils/MatchTableUtils.java @@ -0,0 +1,33 @@ +package com.xzzn.ems.utils; + +import com.xzzn.common.annotation.Excel; +import com.xzzn.common.utils.StringUtils; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * 匹配表工具类 + */ +public class MatchTableUtils { + + /** + * 获取字段注解信息 + */ + public static String getFieldAnnotation(Class clazz, String filedName) + { + List tempFields = new ArrayList<>(); + tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); + for (Field field : tempFields) { + if (StringUtils.equals(filedName, field.getName()) && field.isAnnotationPresent(Excel.class)) + { + Excel column = field.getAnnotation(Excel.class); + return column.name(); + } + } + return null; + } + +} diff --git a/ems-system/src/main/resources/mapper/ems/EmsPointMatchMapper.xml b/ems-system/src/main/resources/mapper/ems/EmsPointMatchMapper.xml index c0560cf..2dd6aad 100644 --- a/ems-system/src/main/resources/mapper/ems/EmsPointMatchMapper.xml +++ b/ems-system/src/main/resources/mapper/ems/EmsPointMatchMapper.xml @@ -24,10 +24,11 @@ + - select id, point_name, match_table, match_field, site_id, device_category, data_point, data_point_name, data_device, data_unit, ip_address, ip_port, data_type, need_diff_device_id, create_by, create_time, update_by, update_time, remark from ems_point_match + select id, point_name, match_table, match_field, site_id, device_category, data_point, data_point_name, data_device, data_unit, ip_address, ip_port, data_type, need_diff_device_id, create_by, create_time, update_by, update_time, remark, device_id from ems_point_match + + + \ No newline at end of file