1.污染值算法迁移

2.增加暂态信息补招
This commit is contained in:
wr
2025-07-25 17:27:18 +08:00
parent 6d5d2a339e
commit 7a0b0cc943
28 changed files with 499 additions and 53 deletions

View File

@@ -37,7 +37,8 @@ public class MeasurementExecutor extends BaseExecutor {
private IDataComAssService dataComAssService;
@Resource
private IPollutionService pollutionService;
@Resource
private IPollutionCalc pollutionCalc;
/**
* 数据质量清洗
*/
@@ -450,6 +451,20 @@ public class MeasurementExecutor extends BaseExecutor {
pollutionService.handleDay(bindCmp.getRequestData());
}
/**
* 监测点污区图
* @param bindCmp
* @return
*/
@LiteflowMethod(value = LiteFlowMethodEnum.IS_ACCESS, nodeId = "dataPollutionCalc", nodeType = NodeTypeEnum.COMMON)
public boolean dataPollutionCalcAccess(NodeComponent bindCmp) {
return isAccess(bindCmp);
}
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "dataPollutionCalc", nodeType = NodeTypeEnum.COMMON)
public void dataPollutionCalcProcess(NodeComponent bindCmp) {
pollutionCalc.calcAllLineValue(bindCmp.getRequestData());
}
/**
* 监测点数据完整性

View File

@@ -0,0 +1,17 @@
package com.njcn.algorithm.service.line;
import com.njcn.algorithm.pojo.bo.CalculatedParam;
/**
* 污染值算法
*/
public interface IPollutionCalc {
/**
* 计算谐波电压、谐波电流
* @param calculatedParam
* @Author: wr
* @Date: 2025/7/24 14:37
*/
void calcAllLineValue(CalculatedParam calculatedParam);
}

View File

@@ -1485,20 +1485,24 @@ public class DataCleanServiceImpl implements IDataCleanService {
pqReasonableRangeDto = map.get(DataCleanEnum.V_Data.getCode());
phaseList = Arrays.asList(pqReasonableRangeDto.getPhaseType().split(","));
if (phaseList.contains(dto.getPhasicType())) {
if (dto.getV1() < (pqReasonableRangeDto.getMinValue()*DataCommonUtils.getVoltageData(line.getVoltageLevel()))
|| dto.getV1() > (pqReasonableRangeDto.getMaxValue()*DataCommonUtils.getVoltageData(line.getVoltageLevel()))) {
//log.info("dataV-基波电压数据异常,已清洗!数据值:{},数据时间:{}", dto.getV1(), dto.getMinTime());
PqDataVerify pqDataVerify = getPqDataVerify(dto.getLineId()
,dto.getMinTime()
,dto.getValueType()
,dto.getPhasicType()
,pqReasonableRangeDto.getIndexCode()
,pqReasonableRangeDto.getIndexName()
,pqReasonableRangeDto.getInfluxdbTableName()
,dto.getV1()
,pqReasonableRangeDto.getMinValue()*DataCommonUtils.getVoltageData(line.getVoltageLevel())
,pqReasonableRangeDto.getMaxValue()*DataCommonUtils.getVoltageData(line.getVoltageLevel()));
list.add(pqDataVerify);
if(ObjectUtil.isNotNull(dto.getV1())){
if (dto.getV1() < (pqReasonableRangeDto.getMinValue()*DataCommonUtils.getVoltageData(line.getVoltageLevel()))
|| dto.getV1() > (pqReasonableRangeDto.getMaxValue()*DataCommonUtils.getVoltageData(line.getVoltageLevel()))) {
//log.info("dataV-基波电压数据异常,已清洗!数据值:{},数据时间:{}", dto.getV1(), dto.getMinTime());
PqDataVerify pqDataVerify = getPqDataVerify(dto.getLineId()
,dto.getMinTime()
,dto.getValueType()
,dto.getPhasicType()
,pqReasonableRangeDto.getIndexCode()
,pqReasonableRangeDto.getIndexName()
,pqReasonableRangeDto.getInfluxdbTableName()
,dto.getV1()
,pqReasonableRangeDto.getMinValue()*DataCommonUtils.getVoltageData(line.getVoltageLevel())
,pqReasonableRangeDto.getMaxValue()*DataCommonUtils.getVoltageData(line.getVoltageLevel()));
list.add(pqDataVerify);
}
}else{
logger.info("vData{}", dto);
}
}
return list;

View File

@@ -815,9 +815,15 @@ public class IDataCrossingServiceImpl implements IDataCrossingService {
//负序电流
if (!CollectionUtils.isEmpty(dataIPONegList)) {
for (DataIDto item : dataIPONegList) {
if (item.getINeg() > overlimit.getINeg()) {
if(ObjectUtil.isNotNull(item.getINeg())){
if (item.getINeg() > overlimit.getINeg()) {
addAbnormalData(iNeg, item.getPhasicType(), item.getValueType(), item.getMinTime(), item.getINeg(), overlimit.getINeg());
}
}else{
System.out.println(item);
addAbnormalData(iNeg, item.getPhasicType(), item.getValueType(), item.getMinTime(), item.getINeg(), overlimit.getINeg());
}
}
}
//频率偏差

View File

@@ -0,0 +1,244 @@
package com.njcn.algorithm.serviceimpl.line;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.njcn.algorithm.pojo.bo.CalculatedParam;
import com.njcn.algorithm.service.line.IPollutionCalc;
import com.njcn.common.utils.PubUtils;
import com.njcn.dataProcess.api.DataHarmRateVFeignClient;
import com.njcn.dataProcess.api.DataIFeignClient;
import com.njcn.dataProcess.api.DataPollutionFeignClient;
import com.njcn.dataProcess.api.DataVFeignClient;
import com.njcn.dataProcess.param.LineCountEvaluateParam;
import com.njcn.dataProcess.pojo.dto.DataHarmDto;
import com.njcn.dataProcess.pojo.dto.DataIDto;
import com.njcn.dataProcess.pojo.dto.DataPollutionD;
import com.njcn.dataProcess.pojo.dto.DataVDto;
import com.njcn.dataProcess.util.TimeUtils;
import com.njcn.device.biz.commApi.CommTerminalGeneralClient;
import com.njcn.device.biz.pojo.dto.LineDevGetDTO;
import com.njcn.device.biz.pojo.po.Overlimit;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.enums.DicDataEnum;
import com.njcn.system.enums.DicDataTypeEnum;
import com.njcn.system.pojo.po.DictData;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
public class PollutionCalcImpl implements IPollutionCalc {
@Resource
private CommTerminalGeneralClient commTerminalGeneralClient;
@Resource
private DicDataFeignClient dicDataFeignClient;
@Resource
private DataVFeignClient dataVFeignClient;
@Resource
private DataHarmRateVFeignClient dataHarmRateVFeignClient;
@Resource
private DataIFeignClient dataIFeignClient;
@Resource
private DataPollutionFeignClient dataPollutionFeignClient;
/**
* 监测点污染值计算,谐波电压&谐波电流
* 1、获取所有监测点
* 2、根据指标获取对应的污染值目前仅做谐波电压
* 注:目前仅支持获取昨天的
*/
@Override
public void calcAllLineValue(CalculatedParam calculatedParam) {
System.out.println("当前执行监测点污染值算法++++++++++++++++++++++++++++++++++");
List<DataPollutionD> list = new ArrayList<>();
List<String> idList = calculatedParam.getIdList();
List<Overlimit> overlimitList = commTerminalGeneralClient.getOverLimitDataByIds(idList).getData();
Map<String, Overlimit> limitMap = overlimitList.stream().collect(Collectors.toMap(Overlimit::getId, Function.identity()));
List<LineDevGetDTO> lineDetailList = commTerminalGeneralClient.getMonitorDetailList(idList).getData();
Map<String, LineDevGetDTO> lineDetailMap = lineDetailList.stream().collect(Collectors.toMap(LineDevGetDTO::getPointId, Function.identity()));
List<DictData> dictDataList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.POLLUTION_CALC.getCode()).getData();
Map<String, String> dictData = dictDataList.stream().collect(Collectors.toMap(DictData::getCode, DictData::getId));
String vHarmonicLimit = dictData.get(DicDataEnum.V_HARMONIC_LIMIT.getCode());
String iAllLimit = dictData.get(DicDataEnum.I_ALL_LIMIT.getCode());
if (CollUtil.isNotEmpty(idList)) {
System.out.println("总共" + idList.size() + "个监测点参与污染值计算,开始执行");
DataPollutionD dataPollutionD;
LineCountEvaluateParam lineParam = new LineCountEvaluateParam();
lineParam.setStartTime(TimeUtils.getBeginOfDay(calculatedParam.getDataDate()));
lineParam.setEndTime(TimeUtils.getEndOfDay(calculatedParam.getDataDate()));
for (String id : idList) {
if (lineDetailMap.containsKey(id)) {
LineDevGetDTO line = lineDetailMap.get(id);
if (limitMap.containsKey(id)) {
Overlimit overlimit = limitMap.get(id);
dataPollutionD = new DataPollutionD();
dataPollutionD.setLineId(id);
dataPollutionD.setDataDate(LocalDateTimeUtil.parseDate(calculatedParam.getDataDate()));
dataPollutionD.setPollutionType(vHarmonicLimit);
lineParam.setValueType(Arrays.asList(line.getTimeInterval() + ""));
lineParam.setLineId(Arrays.asList(id));
List<DataVDto> dataVDtoList = dataVFeignClient.getGroupByTimeDataV(lineParam).getData();
List<DataHarmDto> dataHarmDtoList = dataHarmRateVFeignClient.getGroupByTimeHarmRateV(lineParam).getData();
if (CollUtil.isNotEmpty(dataVDtoList) && CollUtil.isNotEmpty(dataHarmDtoList)) {
//计算谐波电压污染值
dataPollutionD.setValue(PubUtils.doubleRound(2, calcVAllPollutionValue(dataVDtoList, dataHarmDtoList, overlimit) * line.getTimeInterval()));
list.add(dataPollutionD);
}
dataPollutionD = new DataPollutionD();
dataPollutionD.setLineId(id);
dataPollutionD.setDataDate(LocalDateTimeUtil.parseDate(calculatedParam.getDataDate()));
dataPollutionD.setPollutionType(iAllLimit);
List<DataIDto> data = dataIFeignClient.getGroupByTimeDataI(lineParam).getData();
if (CollUtil.isNotEmpty(data)) {
//计算谐波电流污染值
dataPollutionD.setValue(PubUtils.doubleRound(2, calcIAllPollutionValue(data, overlimit) * line.getTimeInterval()));
list.add(dataPollutionD);
}
}
}
}
}
if (CollUtil.isNotEmpty(list)) {
dataPollutionFeignClient.batchInsertion(list);
}
}
/**
* 计算谐波电压的污染值包含了电压总畸变率和谐波电压2~25次
*
* @param dataVDtoList
* @param dataHarmDtoList
* @param overlimit
* @return
*/
private double calcVAllPollutionValue(List<DataVDto> dataVDtoList, List<DataHarmDto> dataHarmDtoList, Overlimit overlimit) {
// 计算时间范围内指标越限百分比
// 总畸变率的限值
List<Double> thdValueList = dataVDtoList.stream().map(DataVDto::getVThd).collect(Collectors.toList());
double thdPollutionValue = calcPollutionValue(overlimit.getUbalance(), thdValueList);
//谐波值2~50次
double harmRateVPollutionValue = calcHarmRateVPollutionValue(overlimit, dataHarmDtoList);
return thdPollutionValue + harmRateVPollutionValue;
}
private double calcIAllPollutionValue(List<DataIDto> dataVDtoList, Overlimit overlimit) {
List<Double> pollutionValue = new ArrayList<>();
// 2次
for (int i = 2; i < 51; i++) {
Float limitValue = getValueByFieldName(overlimit, "iharm" + i);
int finalI = i;
List<Double> valueList = dataVDtoList.stream().map(item -> {
Float valueByFieldName = getValueByFieldName(item, "i" + finalI);
if (Objects.isNull(valueByFieldName)) {
return 0.0;
} else {
return (double) valueByFieldName;
}
}).collect(Collectors.toList());
pollutionValue.add(calcPollutionValue(limitValue, valueList));
}
return pollutionValue.stream().mapToDouble(Double::doubleValue).sum();
}
/**
* 计算谐波电压2~50的越限污染值
*
* @param overlimit 限值
* @param dataHarmRateVList 2~50次的谐波电压值
* @return 谐波电压污染值
*/
private double calcHarmRateVPollutionValue(Overlimit overlimit, List<DataHarmDto> dataHarmRateVList) {
List<Double> pollutionValue = new ArrayList<>();
// 2次
for (int i = 2; i < 51; i++) {
Float limitValue = getValueByFieldName(overlimit, "uharm" + i);
int finalI = i;
List<Double> valueList = dataHarmRateVList.stream().map(item -> {
Float valueByFieldName = getValueByFieldName(item, "v" + finalI);
if (Objects.isNull(valueByFieldName)) {
return 0.0;
} else {
return (double) valueByFieldName;
}
}).collect(Collectors.toList());
pollutionValue.add(calcPollutionValue(limitValue, valueList));
}
return pollutionValue.stream().mapToDouble(Double::doubleValue).sum();
}
/**
* 获取当前组数据的污染值
*
* @param limit 限值
* @param valueList 参考数据
* @return 污染值
*/
private double calcPollutionValue(Float limit, List<Double> valueList) {
double pollutionValue = 0;
// 没有限值的直接返回
if (Objects.isNull(limit) || limit == 0.0f) {
return pollutionValue;
}
// 计算每个数值的越限百分比MOP
List<Double> overLimitPercentList = valueList.stream().map(value -> {
if (Objects.isNull(value)) {
return 0.0;
}
return value * 100 / limit;
}).collect(Collectors.toList());
// 计算每个越限百分比对应的污染值,并求和返回
if (CollUtil.isNotEmpty(overLimitPercentList)) {
pollutionValue = overLimitPercentList.stream().map(item -> {
double value = 0;
if (item >= 100.0 && item < 120.0) {
value = 0.1;
} else if (item >= 120.0 && item < 160.0) {
value = 0.2;
} else if (item >= 160.0 && item < 200.0) {
value = 0.3;
} else if (item >= 200.0) {
value = 0.4;
}
return value;
}).mapToDouble(Double::doubleValue).sum();
}
return pollutionValue;
}
/**
* 根据标记获取属性对应的值
*
* @return 值
*/
public static Float getValueByFieldName(Object obj, String fieldName) {
try {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
Object val = field.get(obj);
if (Objects.isNull(val)) {
return null;
}
if (val instanceof Double) {
Double doubleValue = (Double) val;
return doubleValue.floatValue();
}
return (float) field.get(obj);
} catch (NoSuchFieldException | IllegalAccessException e) {
return 0.0f;
}
}
}

View File

@@ -58,7 +58,7 @@ liteflow:
logging:
config: http://@nacos.url@/nacos/v1/cs/configs?tenant=@nacos.namespace@&group=DEFAULT_GROUP&dataId=logback.xml
level:
root: info
root:
#mybatis配置信息