dev #2

Merged
dashixiong merged 349 commits from dev into main 2026-02-11 01:55:46 +00:00
238 changed files with 26750 additions and 1003 deletions
Showing only changes of commit 8954329ccc - Show all commits

View File

@ -9,6 +9,7 @@ import com.xzzn.common.utils.file.MimeTypeUtils;
import com.xzzn.ems.domain.EmsDevicesSetting; import com.xzzn.ems.domain.EmsDevicesSetting;
import com.xzzn.ems.domain.EmsPointMatch; import com.xzzn.ems.domain.EmsPointMatch;
import com.xzzn.ems.domain.EmsSiteSetting; import com.xzzn.ems.domain.EmsSiteSetting;
import com.xzzn.ems.domain.vo.PointQueryResponse;
import com.xzzn.ems.domain.vo.SiteDeviceListVo; import com.xzzn.ems.domain.vo.SiteDeviceListVo;
import com.xzzn.ems.mapper.EmsPointMatchMapper; import com.xzzn.ems.mapper.EmsPointMatchMapper;
import com.xzzn.ems.service.IEmsDeviceSettingService; import com.xzzn.ems.service.IEmsDeviceSettingService;
@ -145,10 +146,9 @@ public class EmsSiteConfigController extends BaseController{
* 单个站点单个设备点位查询 * 单个站点单个设备点位查询
*/ */
@GetMapping("/getDevicePointList") @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<PointQueryResponse> result = iEmsDeviceSettingService.getSingleSiteDevicePoints(siteId,deviceId,deviceCategory);
List<EmsPointMatch> pointList = emsPointMatchMapper.getSingleSiteDevicePoints(siteId,deviceCategory); return getDataTable2(result);
return getDataTable(pointList);
} }
} }

View File

@ -51,4 +51,9 @@ public class RedisKeyConstants
* BMSD原始数据 redis key * BMSD原始数据 redis key
*/ */
public static final String ORIGINAL_BMSD = "BMSD_"; public static final String ORIGINAL_BMSD = "BMSD_";
/**
* 存放单个设备同步过来的原始数据
*/
public static final String ORIGINAL_MQTT_DATA = "MQTT_";
} }

View File

@ -208,28 +208,42 @@ public class BaseController
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({ "rawtypes", "unchecked" })
protected TableDataInfo getDataTable2(List<?> list) 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(); PageDomain pageDomain = TableSupport.buildPageRequest();
int pageNum = pageDomain.getPageNum(); int pageNum = pageDomain.getPageNum();
int pageSize = pageDomain.getPageSize(); int pageSize = pageDomain.getPageSize();
// 3. 判断分页参数是否有效pageNum和pageSize均为正数时才分页
if (pageNum > 0 && pageSize > 0) { if (pageNum > 0 && pageSize > 0) {
// 计算分页起始和结束索引 // 计算起始索引确保不小于0
int startIndex = (pageNum - 1) * pageSize; int startIndex = Math.max((pageNum - 1) * pageSize, 0);
int endIndex = Math.min(startIndex + pageSize, list.size());
// 防止越界 // 关键修复:若起始索引已超出列表大小,直接返回空列表
if (startIndex >= list.size()) { if (startIndex >= targetList.size()) {
subList = Collections.emptyList(); 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));
} }
// 截取当前页数据 } else {
subList = list.subList(startIndex, endIndex); // 分页参数无效时,返回全部数据
subList = new ArrayList<>(targetList);
} }
// 4. 封装返回结果
TableDataInfo rspData = new TableDataInfo(); TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS); rspData.setCode(HttpStatus.SUCCESS);
rspData.setMsg("查询成功"); rspData.setMsg("查询成功");
rspData.setRows(subList); rspData.setRows(subList);
rspData.setTotal(list.size()); rspData.setTotal(targetList.size());
return rspData; return rspData;
} }

View File

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

View File

@ -6,6 +6,7 @@ import java.util.Map;
import com.xzzn.ems.domain.EmsPointMatch; import com.xzzn.ems.domain.EmsPointMatch;
import com.xzzn.ems.domain.vo.GeneralQueryDataVo; import com.xzzn.ems.domain.vo.GeneralQueryDataVo;
import com.xzzn.ems.domain.vo.PointQueryResponse;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
/** /**
@ -118,5 +119,5 @@ public interface EmsPointMatchMapper
@Param("deviceId")String deviceId); @Param("deviceId")String deviceId);
// 单个站点单个设备点位查询 // 单个站点单个设备点位查询
public List<EmsPointMatch> getSingleSiteDevicePoints(@Param("siteId")String siteId, @Param("deviceCategory")String deviceCategory); public List<PointQueryResponse> getSingleSiteDevicePoints(@Param("siteId")String siteId, @Param("deviceCategory")String deviceCategory);
} }

View File

@ -2,6 +2,8 @@ package com.xzzn.ems.service;
import com.xzzn.common.enums.DeviceCategory; import com.xzzn.common.enums.DeviceCategory;
import com.xzzn.ems.domain.EmsDevicesSetting; import com.xzzn.ems.domain.EmsDevicesSetting;
import com.xzzn.ems.domain.EmsPointMatch;
import com.xzzn.ems.domain.vo.PointQueryResponse;
import java.util.List; import java.util.List;
@ -21,4 +23,6 @@ public interface IEmsDeviceSettingService
public int deleteEmsDevicesSettingById(Long id); public int deleteEmsDevicesSettingById(Long id);
public List<DeviceCategory> getDeviceCategory(); public List<DeviceCategory> getDeviceCategory();
public List<PointQueryResponse> getSingleSiteDevicePoints(String siteId, String deviceId, String deviceCategory);
} }

View File

@ -92,6 +92,9 @@ public class DDSDataProcessServiceImpl extends AbstractBatteryDataProcessor impl
return; return;
} }
// 存放mqtt原始每个设备数据便于后面点位获取数据
redisCache.setCacheObject(RedisKeyConstants.ORIGINAL_MQTT_DATA + SITE_ID + "_" + deviceId, obj);
// 处理相关数据 // 处理相关数据
if (deviceId.contains("BMSD")) { if (deviceId.contains("BMSD")) {
batteryStackDataProcess(deviceId, jsonData); batteryStackDataProcess(deviceId, jsonData);

View File

@ -1,16 +1,22 @@
package com.xzzn.ems.service.impl; 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.enums.DeviceCategory;
import com.xzzn.common.utils.DateUtils; import com.xzzn.common.utils.DateUtils;
import com.xzzn.common.utils.StringUtils; import com.xzzn.common.utils.StringUtils;
import com.xzzn.ems.domain.EmsDevicesSetting; import com.xzzn.ems.domain.EmsDevicesSetting;
import com.xzzn.ems.domain.vo.PointQueryResponse;
import com.xzzn.ems.mapper.EmsDevicesSettingMapper; import com.xzzn.ems.mapper.EmsDevicesSettingMapper;
import com.xzzn.ems.mapper.EmsPointMatchMapper;
import com.xzzn.ems.service.IEmsDeviceSettingService; import com.xzzn.ems.service.IEmsDeviceSettingService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Arrays; import java.util.*;
import java.util.List;
/** /**
* 站点信息 服务层实现 * 站点信息 服务层实现
@ -19,9 +25,14 @@ import java.util.List;
@Service @Service
public class EmsDeviceSettingServiceImpl implements IEmsDeviceSettingService public class EmsDeviceSettingServiceImpl implements IEmsDeviceSettingService
{ {
private static final String DDS_SITE_ID = "021_DDS_01";
@Autowired @Autowired
private EmsDevicesSettingMapper emsDevicesMapper; private EmsDevicesSettingMapper emsDevicesMapper;
@Autowired
private EmsPointMatchMapper emsPointMatchMapper;
@Autowired
private RedisCache redisCache;
/** /**
* 获取设备详细信息 * 获取设备详细信息
* @param id * @param id
@ -106,4 +117,100 @@ public class EmsDeviceSettingServiceImpl implements IEmsDeviceSettingService
List<DeviceCategory> deviceList = Arrays.asList(DeviceCategory.values()); List<DeviceCategory> deviceList = Arrays.asList(DeviceCategory.values());
return deviceList; return deviceList;
} }
@Override
public List<PointQueryResponse> getSingleSiteDevicePoints(String siteId, String deviceId, String deviceCategory) {
List<PointQueryResponse> 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<String, Object> obj = JSON.parseObject(jsonData, new TypeReference<Map<String, Object>>() {});
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<PointQueryResponse> specialDealWithDDSCluster(List<PointQueryResponse> 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<String, Object> obj = JSON.parseObject(jsonData, new TypeReference<Map<String, Object>>() {});
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);
}
} }

View File

@ -85,6 +85,9 @@ public class FXXDataProcessServiceImpl extends AbstractBatteryDataProcessor impl
return; return;
} }
// 存放mqtt原始每个设备数据便于后面点位获取数据
redisCache.setCacheObject(RedisKeyConstants.ORIGINAL_MQTT_DATA + SITE_ID + "_" + deviceId, obj);
if (deviceId.contains("BMSD")) { if (deviceId.contains("BMSD")) {
batteryStackDataProcess(deviceId, jsonData); batteryStackDataProcess(deviceId, jsonData);

View File

@ -318,8 +318,13 @@
ORDER BY t.site_id, t.device_id, valueDate ASC ORDER BY t.site_id, t.device_id, valueDate ASC
</select> </select>
<select id="getSingleSiteDevicePoints" resultMap="EmsPointMatchResult"> <select id="getSingleSiteDevicePoints" resultType="com.xzzn.ems.domain.vo.PointQueryResponse">
<include refid="selectEmsPointMatchVo"/> 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 where 1=1
<if test="siteId != null and siteId != ''"> <if test="siteId != null and siteId != ''">
and site_id = #{siteId} and site_id = #{siteId}