有功功率趋势指标列表详细excel导出

This commit is contained in:
guofeihu
2024-09-10 15:04:54 +08:00
parent bf67652055
commit 024bba337a
9 changed files with 618 additions and 257 deletions

View File

@@ -21,8 +21,10 @@ import com.njcn.prepare.harmonic.pojo.param.RActivePowerRangeParam;
import com.njcn.prepare.harmonic.pojo.po.RActivePowerRangePO;
import com.njcn.prepare.harmonic.service.mysql.event.RActivePowerRangeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
@@ -34,6 +36,7 @@ import java.util.stream.Collectors;
* @author guofeihu
* @since 2024-08-22
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class RActivePowerRangeServiceImpl extends MppServiceImpl<RActivePowerRangeMapper, RActivePowerRangePO> implements RActivePowerRangeService {
@@ -48,20 +51,42 @@ public class RActivePowerRangeServiceImpl extends MppServiceImpl<RActivePowerRan
private DateTimeFormatter formatter = DateTimeFormatter.ofPattern(Param.DATE_FORMAT);
private SimpleDateFormat sdf = new SimpleDateFormat(Param.DATE_FORMAT);
private List<String> PHASE = Arrays.asList(InfluxDBTableConstant.PHASE_TYPE_A,InfluxDBTableConstant.PHASE_TYPE_B,InfluxDBTableConstant.PHASE_TYPE_C);
/**
* 整个算法的业务逻辑:
* 1:查询InfluxDb的功率表:data_harmpower_p
* 2:遍历功率集合将功率(p字段) / line_id监测点绑定的新能源场站中的风电场的额定功率,看落在哪个区间内
* 3:遍历功率集合将每条功率对应的各个指标(指标的所有相别和统计方式都要一一比较)与国标限值比较看看是否越限(功率对应的各个指标详情请见下方)
* --------------------------------指标---------------------------------
* 电压偏差 data_v vu_dev 电压偏差 如果vu_dev>0,使用上偏差限值对比如果vu_dev<0,使用下偏差限值对比
* 谐波电压 data_v v_thd 电压总谐波总谐波畸变率 有一个指标超标,则谐波电压超标
* data_harmrate_v v2-v25 2-25次谐波电压含有率
* 谐波电流 data_i i2-i25 2-25次谐波电流幅值 有一个指标超标,则谐波电压超标
* 三相电压不平衡度 data_v v_unbalance
* 电压波动 data_fluc fluc
* 长时闪变 data_plt plt
* 间谐波电压含有率 data_inharm_v v1-v16 0.5-15.5次间谐波电压含有率 有一个指标超标,则谐波电压超标
* 电流不平衡度 data_i i_unbalance 这个不确定,找宝哥确认下
* @param rActivePowerRangeParam
* @return
*/
@Override
public List<PowerStatisticsTargetVO> record(RActivePowerRangeParam rActivePowerRangeParam) {
if(rActivePowerRangeParam == null){
rActivePowerRangeParam = new RActivePowerRangeParam();
}
//根据事件间隔查询 SELECT * FROM "data_harmpower_p" limit 1 得到P
// 便利 用p / 风电场额定有功功率 * 100% 看落在那个占比
//返回的最终结果
List<PowerStatisticsTargetVO> powerStatisticsTargetVOS = new ArrayList<>();
//定义开始和结束时间
//默认初始化开始和结束时间
String startTime = getTime(rActivePowerRangeParam.getInterval(),0);
String endTime = getTime(rActivePowerRangeParam.getInterval(),1);
//获取时间段内的有功功率集合
List<CommonQueryParam> commonQueryParams = new ArrayList<>();
CommonQueryParam commonQueryParam = new CommonQueryParam();
//控制参数中如果search为true,则获取有功功率集合的时间段内为BaseParam中的searchBeginTime和searchEndTime(用于前端有功功率查询页面相关接口)
if(rActivePowerRangeParam.isSearch()){
startTime = rActivePowerRangeParam.getSearchBeginTime()+Param.BEGIN;
endTime = rActivePowerRangeParam.getSearchEndTime()+Param.END;
@@ -70,25 +95,37 @@ public class RActivePowerRangeServiceImpl extends MppServiceImpl<RActivePowerRan
//时间段
commonQueryParam.setStartTime(startTime);
commonQueryParam.setEndTime(endTime);
//不传统计方式及相别
//临时模拟增加的条件(用于调试主要是数据量太大非常消耗时间)
// commonQueryParam.setDataType("AVG");
// commonQueryParam.setPhasic("A");
// commonQueryParam.setStartTime("2024-09-01 00:00:00");
// commonQueryParam.setEndTime("2024-09-01 00:00:00");
//功率表data_harmpower_p及字段p
commonQueryParam.setTableName(InfluxDBTableConstant.DATA_HARM_POWER_P);
commonQueryParam.setColumnName("p");
commonQueryParams.add(commonQueryParam);
//这边没有设置他的统计方式和相别是因为根据有功功率查询各个指标的时候要把所有的指标和统计方式都查出来一一比较
List<StatisticalDataDTO> dataHarmPowerPS = commonService.getNewDeviceRtDataByTime(commonQueryParams);
//由于前端写死了各个指标的相别(只有A、B、C所以这边直接限制死了)
dataHarmPowerPS = dataHarmPowerPS.stream().filter(param->PHASE.contains(param.getPhaseType())).collect(Collectors.toList());
//有功功率趋势表是按照监测点来划分的 所以这边需要根据监测点来分组
Map<String,List<StatisticalDataDTO>> map = dataHarmPowerPS.stream().collect(Collectors.groupingBy(StatisticalDataDTO::getLineId));
RActivePowerRangeParam finalRActivePowerRangeParam = rActivePowerRangeParam;
//以下这段逻辑较耗时(主要是for循环),主要是要遍历所有的有功功率,在根据有功功率查询各个指标进行比较(最耗时的是有功功率查询各个指标,所以一但有功功率很多则遍历较慢)
log.info("当前遍历的功率根据监测点分组后长度为:{},集合总长为:{},现在开始遍历,{}",map.size(),dataHarmPowerPS.size(),sdf.format(new Date()));
map.forEach((key, value) ->{
//获取监测点的国标限值
List<Overlimit> overlimits = overLimitClient.getOverLimitByLineIds(Arrays.asList(key)).getData();
//该监测点必须要有国标限值
if(overlimits != null && !overlimits.isEmpty()){
Overlimit overlimit = overlimits.get(0);
//获取监测点
LineDTO lineDTO = commLineClient.getLineDetail(key).getData();
//监测点必须绑定新能源站
if(lineDTO != null && lineDTO.getNewStationId() != null){
//获取监测点的新能源站
NewStation newStation = newStationClient.selectById(lineDTO.getNewStationId()).getData();
//风电场
//新能源站有些切必须是风电场
if(newStation != null && com.njcn.device.pq.constant.Param.WINDFARM.equals(newStation.getStationType())){
RActivePowerRangePO rActivePowerRangePO = new RActivePowerRangePO();
rActivePowerRangePO.setLineId(key);
@@ -96,19 +133,27 @@ public class RActivePowerRangeServiceImpl extends MppServiceImpl<RActivePowerRan
rActivePowerRangePO.setId(IdUtil.simpleUUID());
LambdaQueryWrapper<RActivePowerRangePO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(RActivePowerRangePO::getLineId,key).eq(RActivePowerRangePO::getTimeId,LocalDate.now());
//强制刷新
//控制参数-强制刷新
if(finalRActivePowerRangeParam.isRefresh()){
this.baseMapper.delete(lambdaQueryWrapper);
}
//计算各个区间个数
//控制参数-是否查询及查询新增(主要用于harmonic-boot-getDataByLineId方法,避免每次执行都会执行for循环,也即当日执行完一次即可)
if(!this.baseMapper.selectList(lambdaQueryWrapper).isEmpty() && (finalRActivePowerRangeParam.isSearch() && finalRActivePowerRangeParam.isSearchForAdd())){
return;
}
int index = 1;
//耗时开始-计算各个区间个数及是否越限
for(StatisticalDataDTO statisticalDataDTO : value){
log.info("前监测点为:{},遍历第{}条...,现在开始遍历,{}",key,index,sdf.format(new Date()));
PowerStatisticsTargetVO powerStatisticsTargetVO = new PowerStatisticsTargetVO();
//设置时间为当前功率的时间
powerStatisticsTargetVO.setTime(statisticalDataDTO.getTime().atZone(ZoneId.systemDefault()).format(formatter));
//当前功率的p字段 / 风电场额定功率
double temp = statisticalDataDTO.getValue() / Double.parseDouble(newStation.getRatedPower());
if(temp <= 0.1){
//占有率区间个数+1
rActivePowerRangePO.setMinsNum0(rActivePowerRangePO.getMinsNum0() + 1);
//指标越限列表区间区分字段
//指标越限列表区间区分字段(用于前端查询)
powerStatisticsTargetVO.setField("0");
//判断每个指标是否越限(根据type来区分设置到哪个区间对应的是否越限字段)
installLimit(rActivePowerRangePO,statisticalDataDTO,overlimit,0,powerStatisticsTargetVO);
@@ -149,8 +194,10 @@ public class RActivePowerRangeServiceImpl extends MppServiceImpl<RActivePowerRan
powerStatisticsTargetVO.setField("9");
installLimit(rActivePowerRangePO,statisticalDataDTO,overlimit,9,powerStatisticsTargetVO);
}
//重点说明:powerStatisticsTargetVO结构(维度)为:time可能多组相同,取决于功率表data_harmpower_p中的相别及统计方式,标识每个指标是否越限,总之一句话:当前时间中八个指标是否越限及他们的相别和统计方式是什么
//重点说明:powerStatisticsTargetVO结构(维度)为:time可能多组相同,取决于功率表data_harmpower_p中的相别及统计方式,标识每个指标是否越限,总之一句话:每条数据当前时间中八个指标是否越限及他们的相别和统计方式是什么
powerStatisticsTargetVOS.add(powerStatisticsTargetVO);
log.info("前监测点为:{},遍历第{}条...,遍历结束,{}",key,index,sdf.format(new Date()));
index++;
}
//根据日期及lineId当天不能重复执行
if(this.baseMapper.selectList(lambdaQueryWrapper).isEmpty() && (finalRActivePowerRangeParam.isSearch() && finalRActivePowerRangeParam.isSearchForAdd() || !finalRActivePowerRangeParam.isSearch())){
@@ -160,15 +207,23 @@ public class RActivePowerRangeServiceImpl extends MppServiceImpl<RActivePowerRan
}
}
});
//区间过滤下
log.info("当前遍历的功率根据监测点分组后长度为:{},集合总长为:{},遍历结束,{}",map.size(),dataHarmPowerPS.size(),sdf.format(new Date()));
//区间过滤下(用于前端查询)
if(rActivePowerRangeParam.isSearch()){
return powerStatisticsTargetVOS.stream().filter(param->param.getField().equals(finalRActivePowerRangeParam.getField())).collect(Collectors.toList());
if(finalRActivePowerRangeParam.getField() != null){
return powerStatisticsTargetVOS.stream().filter(param->param.getField().equals(finalRActivePowerRangeParam.getField())).collect(Collectors.toList());
}
return powerStatisticsTargetVOS;
}
return null;
}
private void installLimit(RActivePowerRangePO rActivePowerRangePO,StatisticalDataDTO statisticalDataDTO,Overlimit overlimit,int type,PowerStatisticsTargetVO powerStatisticsTargetVO){
//以下的结果集按道理最多只有一条(因为确定的相别统计方式及开始和结束时间都一致)
//记录统计方式
powerStatisticsTargetVO.setValueType(statisticalDataDTO.getValueType());
//记录相别
powerStatisticsTargetVO.setPhasicType(statisticalDataDTO.getPhaseType());
//以下的结果集按道理最多只有一条(因为确定的相别统计方式及开始和结束时间都一致,除了有谐波次数的指标)
//电压偏差
List<StatisticalDataDTO> vu_dev = commonQuery(InfluxDBTableConstant.DATA_V,"vu_dev",statisticalDataDTO,null,null);
//谐波电压
@@ -188,113 +243,133 @@ public class RActivePowerRangeServiceImpl extends MppServiceImpl<RActivePowerRan
List<StatisticalDataDTO> i_unbalance = commonQuery(InfluxDBTableConstant.DATA_I,"i_unbalance",statisticalDataDTO,null,null);
//此标识用来记录当前区间下指标是否越限(0%~10%是否越限,10%~20%是否越限.....)
boolean isLimit = false;
//电压偏差是否越限比较
//电压偏差国标限制
//电压偏差国标限值
powerStatisticsTargetVO.setVoltageOffsetLimit(overlimit.getVoltageDev());
//电压偏差是否越限比较
for(StatisticalDataDTO dto : vu_dev){
//电压偏差具体值
powerStatisticsTargetVO.setVoltageOffsetData(dto.getValue());
//电压偏差国标限值有额外的判断
if(dto.getValue()>0){
powerStatisticsTargetVO.setVoltageOffsetLimit(overlimit.getVoltageDev());
}else{
powerStatisticsTargetVO.setVoltageOffsetLimit(overlimit.getUvoltageDev());
}
//如果vu_dev>0,使用上偏差限值对比如果vu_dev<0,使用下偏差限值对比
if((dto.getValue()>0 && Double.compare(dto.getValue(),overlimit.getVoltageDev())>0)
|| (dto.getValue()<0 && Double.compare(dto.getValue(),overlimit.getUvoltageDev())>0)){
isLimit = true;
//标志电压偏差越限
powerStatisticsTargetVO.setVoltageOffset(1);
//记录电压偏差越限的相别
powerStatisticsTargetVO.setPhasicType(dto.getPhaseType());
//记录电压偏差越限的统计方式
powerStatisticsTargetVO.setValueType(dto.getValueType());
}
//电压偏差国标限制有判断
if(dto.getValue()>0){
powerStatisticsTargetVO.setVoltageOffsetLimit(overlimit.getVoltageDev());
}else{
powerStatisticsTargetVO.setVoltageOffsetLimit(overlimit.getUvoltageDev());
}
}
//谐波电压比较较为特殊需要比较两个点(以v为主)
//谐波电压是否越限比较
//谐波电压国标限制
powerStatisticsTargetVO.setVTimesLimit(overlimit.getUaberrance());
for(StatisticalDataDTO dto : v_thd){
if(Double.compare(dto.getValue(),overlimit.getUaberrance())>0){
isLimit = true;
powerStatisticsTargetVO.setVTimes(1);
powerStatisticsTargetVO.setPhasicType(dto.getPhaseType());
powerStatisticsTargetVO.setValueType(dto.getValueType());
}
}
int num = 2;
for(StatisticalDataDTO dto : v){
if(frequencyCompare(overlimit,2,50,dto.getValue(),"uharm")){
isLimit = true;
powerStatisticsTargetVO.setVTimes(1);
powerStatisticsTargetVO.setPhasicType(dto.getPhaseType());
powerStatisticsTargetVO.setValueType(dto.getValueType());
Float value = frequencyValue(overlimit,num,"uharm");
if(value != null){
//记录谐波电压2到25次国标限值(当然这里还是要以influxDb里为主,虽然当前遍历的集合明确查询2-25次但是为了防止influxDb可能缺失一些次数的数据,所以国标限值次数跟着influxDb走)
powerStatisticsTargetVO.getVTimesLimit().add(value);
//谐波电压具体值
powerStatisticsTargetVO.getVTimesData().add(dto.getValue());
if(Double.compare(dto.getValue(),value)>0){
isLimit = true;
//标志谐波电压越限
powerStatisticsTargetVO.setVTimes(1);
}
}
num++;
}
num = 2;
//谐波电流是否越限比较
//谐波电流国标限制(由于有谐波次数所以这边直接默认取第一个)
powerStatisticsTargetVO.setVTimesLimit(overlimit.getIharm2());
for(StatisticalDataDTO dto : i){
if(frequencyCompare(overlimit,2,25,dto.getValue(),"iharm")){
isLimit = true;
powerStatisticsTargetVO.setITimes(1);
powerStatisticsTargetVO.setPhasicType(dto.getPhaseType());
powerStatisticsTargetVO.setValueType(dto.getValueType());
Float value = frequencyValue(overlimit,num,"iharm");
if(value != null){
//记录谐波电流2到25次国标限值(当然这里还是要以influxDb里为主,虽然当前遍历的集合明确查询2-25次但是为了防止influxDb可能缺失一些次数的数据,所以国标限值次数跟着influxDb走)
powerStatisticsTargetVO.getITimesLimit().add(value);
//谐波电流具体值
powerStatisticsTargetVO.getITimesData().add(dto.getValue());
if(Double.compare(dto.getValue(),value)>0){
isLimit = true;
//标志谐波电流越限
powerStatisticsTargetVO.setITimes(1);
}
}
num++;
}
//三相电压不平衡度是否越限比较
//三相电压不平衡度国标限制
//三相电压不平衡度国标限值
powerStatisticsTargetVO.setUbalanceLimit(overlimit.getUbalance());
//三相电压不平衡度是否越限比较
for(StatisticalDataDTO dto : v_unbalance){
//三相电压不平衡度具体值
powerStatisticsTargetVO.setUbalanceData(dto.getValue());
if(Double.compare(dto.getValue(),overlimit.getUbalance())>0){
isLimit = true;
//标志三相电压不平衡度越限
powerStatisticsTargetVO.setUbalance(1);
powerStatisticsTargetVO.setPhasicType(dto.getPhaseType());
powerStatisticsTargetVO.setValueType(dto.getValueType());
}
}
//电压波动是否越限比较
//电压波动国标限制
//电压波动国标限值
powerStatisticsTargetVO.setVoltageFluctuationLimit(overlimit.getVoltageFluctuation());
//电压波动是否越限比较
for(StatisticalDataDTO dto : fluc){
//电压波动具体值
powerStatisticsTargetVO.setVoltageFluctuationData(dto.getValue());
if(Double.compare(dto.getValue(),overlimit.getVoltageFluctuation())>0){
isLimit = true;
//标志电压波动越限
powerStatisticsTargetVO.setVoltageFluctuation(1);
powerStatisticsTargetVO.setPhasicType(dto.getPhaseType());
powerStatisticsTargetVO.setValueType(dto.getValueType());
}
}
//长时闪变是否越限比较
//长时闪变国标限制
//长时闪变国标限值
powerStatisticsTargetVO.setFlickerLimit(overlimit.getFlicker());
//长时闪变是否越限比较
for(StatisticalDataDTO dto : plt){
//长时闪变具体值
powerStatisticsTargetVO.setFlickerData(dto.getValue());
if(Double.compare(dto.getValue(),overlimit.getFlicker())>0){
isLimit = true;
//标志长时闪变越限
powerStatisticsTargetVO.setFlicker(1);
powerStatisticsTargetVO.setPhasicType(dto.getPhaseType());
powerStatisticsTargetVO.setValueType(dto.getValueType());
}
}
num = 1;
//间谐波电压含有率是否越限比较
//间谐波电压含有率国标限制(由于有谐波次数所以这边直接默认取第一个)
powerStatisticsTargetVO.setInterHarmonicLimit(overlimit.getInuharm1());
for(StatisticalDataDTO dto : v1){
if(frequencyCompare(overlimit,1,16,dto.getValue(),"inuharm")){
isLimit = true;
powerStatisticsTargetVO.setInterHarmonic(1);
powerStatisticsTargetVO.setPhasicType(dto.getPhaseType());
powerStatisticsTargetVO.setValueType(dto.getValueType());
Float value = frequencyValue(overlimit,num,"inuharm");
if(value != null){
//记录间谐波电压含有率1到16次国标限值(当然这里还是要以influxDb里为主,虽然当前遍历的集合明确查询1-16次但是为了防止influxDb可能缺失一些次数的数据,所以国标限值次数跟着influxDb走)
powerStatisticsTargetVO.getInterHarmonicLimit().add(value);
//间谐波电压含有率具体值
powerStatisticsTargetVO.getInterHarmonicData().add(dto.getValue());
if(Double.compare(dto.getValue(),value)>0){
isLimit = true;
//标志间谐波电压含有率越限
powerStatisticsTargetVO.setInterHarmonic(1);
}
}
num++;
}
//电流不平衡度是否越限比较
//间谐波电压含有率国标限制
//电流不平衡度国标限值
powerStatisticsTargetVO.setSequenceCurrentUnbalanceLimit(overlimit.getINeg());
//电流不平衡度是否越限比较
for(StatisticalDataDTO dto : i_unbalance){
//电流不平衡度具体值
powerStatisticsTargetVO.setSequenceCurrentUnbalanceData(dto.getValue());
if(Double.compare(dto.getValue(),overlimit.getINeg())>0){
isLimit = true;
//标志电流不平衡度越限
powerStatisticsTargetVO.setSequenceCurrentUnbalance(1);
powerStatisticsTargetVO.setPhasicType(dto.getPhaseType());
powerStatisticsTargetVO.setValueType(dto.getValueType());
}
}
//区间是否越限标识
switch (type){
case 0:
if(isLimit) rActivePowerRangePO.setIsOrNot0(1);
@@ -329,11 +404,13 @@ public class RActivePowerRangeServiceImpl extends MppServiceImpl<RActivePowerRan
}
}
//组装公共查询
//组装公共查询(有谐波次数查询和没有谐波次数查询)
private List<StatisticalDataDTO> commonQuery(String tableName,String columnName,StatisticalDataDTO statisticalDataDTO,Integer start,Integer end){
List<CommonQueryParam> commonQueryParams = new ArrayList<>();
//不管哪种时间是固定的
String time = statisticalDataDTO.getTime().atZone(ZoneId.systemDefault()).format(formatter);
CommonQueryParam commonQueryParam = new CommonQueryParam();
//无谐波次数查询
if(start == null){
commonQueryParam.setStartTime(time);
commonQueryParam.setEndTime(time);
@@ -344,6 +421,7 @@ public class RActivePowerRangeServiceImpl extends MppServiceImpl<RActivePowerRan
commonQueryParam.setColumnName(columnName);
commonQueryParams.add(commonQueryParam);
}else{
//有谐波次数查询
for (int i = start; i <= end; i++) {
commonQueryParam = new CommonQueryParam();
commonQueryParam.setStartTime(time);
@@ -359,22 +437,20 @@ public class RActivePowerRangeServiceImpl extends MppServiceImpl<RActivePowerRan
return commonService.getNewDeviceRtDataByTime(commonQueryParams);
}
private boolean frequencyCompare(Overlimit overlimit,int start,int end,Double value,String flag){
Class clazz = overlimit.getClass();
//反射获取国标限值对应的字段值
private Float frequencyValue(Overlimit overlimit,int num,String flag){
try {
for (int i = start; i <= end; i++) {
Field field = clazz.getDeclaredField(flag+i);
field.setAccessible(true);
if(Double.compare(value,Float.parseFloat(field.get(overlimit).toString()))>0){
return true;
}
}
Class clazz = overlimit.getClass();
Field field = clazz.getDeclaredField(flag+num);
field.setAccessible(true);
return Float.parseFloat(field.get(overlimit).toString());
} catch (Exception e) {
e.printStackTrace();
}
return false;
return null;
}
//根据时间间隔获取间隔前时间或获取昨晚最晚时间
private String getTime(long interval,int type){
DateTimeFormatter sdf = DateTimeFormatter.ofPattern(DateUtils.DATE_FORMAT_10);
LocalDate yesterday;
@@ -396,6 +472,7 @@ public class RActivePowerRangeServiceImpl extends MppServiceImpl<RActivePowerRan
if(!rActivePowerRangePOS.isEmpty()){
RActivePowerRangePO rActivePowerRangePO = new RActivePowerRangePO();
rActivePowerRangePO.setLineId(lineId);
//多条记录则次数累加,是否越限只有有一个区间越限则统一视为该区间越限
for(RActivePowerRangePO rangePO : rActivePowerRangePOS){
rActivePowerRangePO.setMinsNum0(rangePO.getMinsNum0()+rActivePowerRangePO.getMinsNum0());
rActivePowerRangePO.setMinsNum1(rangePO.getMinsNum1()+rActivePowerRangePO.getMinsNum1());