diff --git a/ems-admin/src/main/java/com/xzzn/web/controller/ems/EmsSiteConfigController.java b/ems-admin/src/main/java/com/xzzn/web/controller/ems/EmsSiteConfigController.java index 5951959..3f152b8 100644 --- a/ems-admin/src/main/java/com/xzzn/web/controller/ems/EmsSiteConfigController.java +++ b/ems-admin/src/main/java/com/xzzn/web/controller/ems/EmsSiteConfigController.java @@ -9,6 +9,7 @@ import com.xzzn.common.utils.file.MimeTypeUtils; import com.xzzn.ems.domain.EmsDevicesSetting; import com.xzzn.ems.domain.EmsPointMatch; import com.xzzn.ems.domain.EmsSiteSetting; +import com.xzzn.ems.domain.vo.PointQueryResponse; import com.xzzn.ems.domain.vo.SiteDeviceListVo; import com.xzzn.ems.mapper.EmsPointMatchMapper; import com.xzzn.ems.service.IEmsDeviceSettingService; @@ -145,10 +146,9 @@ public class EmsSiteConfigController extends BaseController{ * 单个站点单个设备点位查询 */ @GetMapping("/getDevicePointList") - public TableDataInfo getDevicePointList(@RequestParam String siteId,@RequestParam String deviceCategory) + public TableDataInfo getDevicePointList(@RequestParam String siteId,@RequestParam String deviceId,@RequestParam String deviceCategory) { - startPage(); - List pointList = emsPointMatchMapper.getSingleSiteDevicePoints(siteId,deviceCategory); - return getDataTable(pointList); + List result = iEmsDeviceSettingService.getSingleSiteDevicePoints(siteId,deviceId,deviceCategory); + return getDataTable2(result); } } 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 e16229c..408dc42 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 @@ -51,4 +51,9 @@ public class RedisKeyConstants * BMSD原始数据 redis key */ public static final String ORIGINAL_BMSD = "BMSD_"; + + /** + * 存放单个设备同步过来的原始数据 + */ + public static final String ORIGINAL_MQTT_DATA = "MQTT_"; } diff --git a/ems-common/src/main/java/com/xzzn/common/core/controller/BaseController.java b/ems-common/src/main/java/com/xzzn/common/core/controller/BaseController.java index a05a357..6d1fb1b 100644 --- a/ems-common/src/main/java/com/xzzn/common/core/controller/BaseController.java +++ b/ems-common/src/main/java/com/xzzn/common/core/controller/BaseController.java @@ -208,28 +208,42 @@ public class BaseController @SuppressWarnings({ "rawtypes", "unchecked" }) protected TableDataInfo getDataTable2(List list) { - List subList = new ArrayList<>(); - // 分页梳理 + // 1. 处理原列表为null的情况,避免空指针 + List targetList = (list == null) ? Collections.emptyList() : list; + List subList; + + // 2. 获取分页参数 PageDomain pageDomain = TableSupport.buildPageRequest(); int pageNum = pageDomain.getPageNum(); int pageSize = pageDomain.getPageSize(); + + // 3. 判断分页参数是否有效(pageNum和pageSize均为正数时才分页) if (pageNum > 0 && pageSize > 0) { - // 计算分页起始和结束索引 - int startIndex = (pageNum - 1) * pageSize; - int endIndex = Math.min(startIndex + pageSize, list.size()); - // 防止越界 - if (startIndex >= list.size()) { - subList = Collections.emptyList(); + // 计算起始索引(确保不小于0) + int startIndex = Math.max((pageNum - 1) * pageSize, 0); + + // 关键修复:若起始索引已超出列表大小,直接返回空列表 + if (startIndex >= targetList.size()) { + subList = Collections.emptyList(); + } else { + // 计算结束索引(不超过列表大小,且不小于起始索引) + int endIndex = Math.min(startIndex + pageSize, targetList.size()); + endIndex = Math.max(endIndex, startIndex); // 防止endIndex < startIndex + + // 截取子列表(转换为新ArrayList,避免视图依赖) + subList = new ArrayList<>(targetList.subList(startIndex, endIndex)); } - // 截取当前页数据 - subList = list.subList(startIndex, endIndex); + } else { + // 分页参数无效时,返回全部数据 + subList = new ArrayList<>(targetList); } + // 4. 封装返回结果 TableDataInfo rspData = new TableDataInfo(); rspData.setCode(HttpStatus.SUCCESS); rspData.setMsg("查询成功"); rspData.setRows(subList); - rspData.setTotal(list.size()); + rspData.setTotal(targetList.size()); return rspData; } diff --git a/ems-system/src/main/java/com/xzzn/ems/domain/vo/PointQueryResponse.java b/ems-system/src/main/java/com/xzzn/ems/domain/vo/PointQueryResponse.java new file mode 100644 index 0000000..e03cff5 --- /dev/null +++ b/ems-system/src/main/java/com/xzzn/ems/domain/vo/PointQueryResponse.java @@ -0,0 +1,96 @@ +package com.xzzn.ems.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.xzzn.common.annotation.Excel; + +import java.util.Date; + +/** + * 设备列表-点位详情返回 + */ +public class PointQueryResponse +{ + /** 点位名称 */ + @Excel(name = "点位名称") + private String pointName; + + /** 数据点位 */ + @Excel(name = "数据点位") + private String dataPoint; + + /** 数据点位名称 */ + @Excel(name = "数据点位名称") + private String dataPointName; + + /** 数据点位来源设备 */ + @Excel(name = "数据点位来源设备") + private String dataDevice; + + /** 数据点位来源设备 */ + @Excel(name = "点位最新数据") + private Object pointValue; + + /** 更新时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + /** 点位是否需要匹配多设备 */ + @Excel(name = "点位最新数据") + private int isNeedDeviceId; + + public int getIsNeedDeviceId() { + return isNeedDeviceId; + } + + public void setIsNeedDeviceId(int isNeedDeviceId) { + this.isNeedDeviceId = isNeedDeviceId; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public Object getPointValue() { + return pointValue; + } + + public void setPointValue(Object pointValue) { + this.pointValue = pointValue; + } + + public String getDataDevice() { + return dataDevice; + } + + public void setDataDevice(String dataDevice) { + this.dataDevice = dataDevice; + } + + public String getDataPointName() { + return dataPointName; + } + + public void setDataPointName(String dataPointName) { + this.dataPointName = dataPointName; + } + + public String getDataPoint() { + return dataPoint; + } + + public void setDataPoint(String dataPoint) { + this.dataPoint = dataPoint; + } + + public String getPointName() { + return pointName; + } + + public void setPointName(String pointName) { + this.pointName = pointName; + } +} 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 d402fba..fd1c646 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 @@ -6,6 +6,7 @@ import java.util.Map; import com.xzzn.ems.domain.EmsPointMatch; import com.xzzn.ems.domain.vo.GeneralQueryDataVo; +import com.xzzn.ems.domain.vo.PointQueryResponse; import org.apache.ibatis.annotations.Param; /** @@ -118,5 +119,5 @@ public interface EmsPointMatchMapper @Param("deviceId")String deviceId); // 单个站点单个设备点位查询 - public List getSingleSiteDevicePoints(@Param("siteId")String siteId, @Param("deviceCategory")String deviceCategory); + public List getSingleSiteDevicePoints(@Param("siteId")String siteId, @Param("deviceCategory")String deviceCategory); } diff --git a/ems-system/src/main/java/com/xzzn/ems/service/IEmsDeviceSettingService.java b/ems-system/src/main/java/com/xzzn/ems/service/IEmsDeviceSettingService.java index 3340e50..dcecb19 100644 --- a/ems-system/src/main/java/com/xzzn/ems/service/IEmsDeviceSettingService.java +++ b/ems-system/src/main/java/com/xzzn/ems/service/IEmsDeviceSettingService.java @@ -2,6 +2,8 @@ package com.xzzn.ems.service; import com.xzzn.common.enums.DeviceCategory; import com.xzzn.ems.domain.EmsDevicesSetting; +import com.xzzn.ems.domain.EmsPointMatch; +import com.xzzn.ems.domain.vo.PointQueryResponse; import java.util.List; @@ -21,4 +23,6 @@ public interface IEmsDeviceSettingService public int deleteEmsDevicesSettingById(Long id); public List getDeviceCategory(); + + public List getSingleSiteDevicePoints(String siteId, String deviceId, String deviceCategory); } diff --git a/ems-system/src/main/java/com/xzzn/ems/service/impl/DDSDataProcessServiceImpl.java b/ems-system/src/main/java/com/xzzn/ems/service/impl/DDSDataProcessServiceImpl.java index e527c2f..3689c55 100644 --- a/ems-system/src/main/java/com/xzzn/ems/service/impl/DDSDataProcessServiceImpl.java +++ b/ems-system/src/main/java/com/xzzn/ems/service/impl/DDSDataProcessServiceImpl.java @@ -92,6 +92,9 @@ public class DDSDataProcessServiceImpl extends AbstractBatteryDataProcessor impl return; } + // 存放mqtt原始每个设备数据,便于后面点位获取数据 + redisCache.setCacheObject(RedisKeyConstants.ORIGINAL_MQTT_DATA + SITE_ID + "_" + deviceId, obj); + // 处理相关数据 if (deviceId.contains("BMSD")) { batteryStackDataProcess(deviceId, jsonData); diff --git a/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsDeviceSettingServiceImpl.java b/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsDeviceSettingServiceImpl.java index 1837a49..ee537ee 100644 --- a/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsDeviceSettingServiceImpl.java +++ b/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsDeviceSettingServiceImpl.java @@ -1,16 +1,22 @@ package com.xzzn.ems.service.impl; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.alibaba.fastjson2.TypeReference; +import com.xzzn.common.constant.RedisKeyConstants; +import com.xzzn.common.core.redis.RedisCache; import com.xzzn.common.enums.DeviceCategory; import com.xzzn.common.utils.DateUtils; import com.xzzn.common.utils.StringUtils; import com.xzzn.ems.domain.EmsDevicesSetting; +import com.xzzn.ems.domain.vo.PointQueryResponse; import com.xzzn.ems.mapper.EmsDevicesSettingMapper; +import com.xzzn.ems.mapper.EmsPointMatchMapper; import com.xzzn.ems.service.IEmsDeviceSettingService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.Arrays; -import java.util.List; +import java.util.*; /** * 站点信息 服务层实现 @@ -19,9 +25,14 @@ import java.util.List; @Service public class EmsDeviceSettingServiceImpl implements IEmsDeviceSettingService { + private static final String DDS_SITE_ID = "021_DDS_01"; + @Autowired private EmsDevicesSettingMapper emsDevicesMapper; - + @Autowired + private EmsPointMatchMapper emsPointMatchMapper; + @Autowired + private RedisCache redisCache; /** * 获取设备详细信息 * @param id @@ -106,4 +117,100 @@ public class EmsDeviceSettingServiceImpl implements IEmsDeviceSettingService List deviceList = Arrays.asList(DeviceCategory.values()); return deviceList; } + + @Override + public List getSingleSiteDevicePoints(String siteId, String deviceId, String deviceCategory) { + List response = emsPointMatchMapper.getSingleSiteDevicePoints(siteId,deviceCategory); + + // 电动所的电池簇特殊处理-来源pcs+bmsd + if (siteId.equals(DDS_SITE_ID) && DeviceCategory.CLUSTER.getCode().equals(deviceCategory)) { + response = specialDealWithDDSCluster(response,siteId,deviceId); + return response; + } + + // 从redis取最新数据 + //String test = redisCache.getCacheObject(RedisKeyConstants.ORIGINAL_MQTT_DATA + siteId + "_" + deviceId); + JSONObject mqttJson = redisCache.getCacheObject(RedisKeyConstants.ORIGINAL_MQTT_DATA + siteId + "_" + deviceId); + if(mqttJson == null){ + return response; + } + String deviceFromMqtt = mqttJson.get("Device").toString(); + String jsonData = mqttJson.get("Data").toString(); + if (StringUtils.isEmpty(jsonData) || !deviceId.equals(deviceFromMqtt)) { + return response; + } + + Map obj = JSON.parseObject(jsonData, new TypeReference>() {}); + for (PointQueryResponse pointInfo : response) { + String dataKey = pointInfo.getDataPoint(); + int isNeedDeviceId = pointInfo.getIsNeedDeviceId(); + if (isNeedDeviceId == 1) {// 需要根据deviceId拼接point + dataKey = deviceId + dataKey; + pointInfo.setDataPoint(dataKey); + } + pointInfo.setPointValue(obj.get(dataKey)); + Long updateTime = Long.valueOf(mqttJson.get("timestamp").toString()); + Date latestUpdateTime = convertUpdateTime(updateTime); + pointInfo.setUpdateTime(latestUpdateTime); + } + + return response; + } + + // 对于dds的电池簇点位最新数据获取特殊处理 + private List specialDealWithDDSCluster(List response, String siteId, String deviceId) { + JSONObject mergedData = new JSONObject(); + + // 数据来源pcs + JSONObject pcsJson = redisCache.getCacheObject(RedisKeyConstants.ORIGINAL_MQTT_DATA + siteId + "_PCS"); + if (pcsJson != null) { + JSONObject data = pcsJson.getJSONObject("Data"); + mergedData.putAll(data); + } + // 根据deviceId获取父类bmsd + String bmsdDeviceId = deviceId.replace("BMSC","BMSD"); + JSONObject bmsdJson = redisCache.getCacheObject(RedisKeyConstants.ORIGINAL_MQTT_DATA + siteId + "_" + bmsdDeviceId); + if (bmsdJson != null) { + JSONObject data = bmsdJson.getJSONObject("Data"); + mergedData.putAll(data); + } + + String jsonData = mergedData.toString(); + Map obj = JSON.parseObject(jsonData, new TypeReference>() {}); + for (PointQueryResponse pointInfo : response) { + String dataKey = pointInfo.getDataPoint(); + Long updateTime = Long.valueOf(bmsdJson.get("timestamp").toString()); + int isNeedDeviceId = pointInfo.getIsNeedDeviceId(); + if (isNeedDeviceId == 1 && "PCS".equals(pointInfo.getDataDevice())) {// 需要根据deviceId拼接point + dataKey = deviceId + dataKey; + updateTime = Long.valueOf(pcsJson.get("timestamp").toString()); + } else if (isNeedDeviceId == 1 && "BMSD".equals(pointInfo.getDataDevice())){ + dataKey = bmsdDeviceId + dataKey; + } + pointInfo.setDataPoint(dataKey); + pointInfo.setPointValue(obj.get(dataKey)); + Date latestUpdateTime = convertUpdateTime(updateTime); + pointInfo.setUpdateTime(latestUpdateTime); + } + return response; + } + + private Date convertUpdateTime(Long updateTime) { + if (updateTime == null) { + return null; + } + + // 兼容10位(秒级)和13位(毫秒级) + int length = String.valueOf(updateTime).length(); + if (length == 10) { // 10位秒级 -> 转换为毫秒级 + updateTime *= 1000; + } else if (length != 13) { // 既不是10位也不是13位,视为非法 + System.err.println("时间戳格式错误,必须是10位(秒)或13位(毫秒)"); + return null; + } + + // 3. 转换为Date + return new Date(updateTime); + } + } diff --git a/ems-system/src/main/java/com/xzzn/ems/service/impl/FXXDataProcessServiceImpl.java b/ems-system/src/main/java/com/xzzn/ems/service/impl/FXXDataProcessServiceImpl.java index 01f7427..fe2d5ac 100644 --- a/ems-system/src/main/java/com/xzzn/ems/service/impl/FXXDataProcessServiceImpl.java +++ b/ems-system/src/main/java/com/xzzn/ems/service/impl/FXXDataProcessServiceImpl.java @@ -85,6 +85,9 @@ public class FXXDataProcessServiceImpl extends AbstractBatteryDataProcessor impl return; } + // 存放mqtt原始每个设备数据,便于后面点位获取数据 + redisCache.setCacheObject(RedisKeyConstants.ORIGINAL_MQTT_DATA + SITE_ID + "_" + deviceId, obj); + if (deviceId.contains("BMSD")) { batteryStackDataProcess(deviceId, jsonData); diff --git a/ems-system/src/main/resources/mapper/ems/EmsPointMatchMapper.xml b/ems-system/src/main/resources/mapper/ems/EmsPointMatchMapper.xml index 753e95e..7b6b290 100644 --- a/ems-system/src/main/resources/mapper/ems/EmsPointMatchMapper.xml +++ b/ems-system/src/main/resources/mapper/ems/EmsPointMatchMapper.xml @@ -318,8 +318,13 @@ ORDER BY t.site_id, t.device_id, valueDate ASC - + select t.point_name as pointName, + t.data_point as dataPoint, + t.data_point_name as dataPointName, + t.data_device as dataDevice, + t.need_diff_device_id as isNeedDeviceId + from ems_point_match t where 1=1 and site_id = #{siteId}