diff --git a/.gitignore b/.gitignore index 4632c4bd9..15cc7a6c9 100644 --- a/.gitignore +++ b/.gitignore @@ -44,4 +44,7 @@ yarn.lock rebel.xml !DmJdbcDriver18.jar -!kingbase8-8.6.0.jar \ No newline at end of file +!kingbase8-8.6.0.jar +/.fastRequest/collections/Root/Default Group/directory.json +/.fastRequest/collections/Root/directory.json +/.fastRequest/config/fastRequestCurrentProjectConfig.json diff --git a/pqs-common/common-event/.mvn/wrapper/maven-wrapper.properties b/pqs-common/common-event/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 000000000..2e76e189d --- /dev/null +++ b/pqs-common/common-event/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/pqs-common/common-event/pom.xml b/pqs-common/common-event/pom.xml new file mode 100644 index 000000000..8aa174087 --- /dev/null +++ b/pqs-common/common-event/pom.xml @@ -0,0 +1,36 @@ + + + + pqs-common + com.njcn + 1.0.0 + + 4.0.0 + common-event + common-event + + 8 + 8 + + + + com.njcn + common-core + ${project.version} + + + com.njcn + common-echarts + ${project.version} + + + com.njcn + common-oss + ${project.version} + + + + + + diff --git a/pqs-common/common-event/src/main/java/com/njcn/event/file/component/WaveFileComponent.java b/pqs-common/common-event/src/main/java/com/njcn/event/file/component/WaveFileComponent.java new file mode 100644 index 000000000..2ffaaebb9 --- /dev/null +++ b/pqs-common/common-event/src/main/java/com/njcn/event/file/component/WaveFileComponent.java @@ -0,0 +1,1289 @@ +package com.njcn.event.file.component; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.text.StrPool; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.StrUtil; +import com.njcn.common.pojo.enums.response.CommonResponseEnum; +import com.njcn.common.pojo.exception.BusinessException; +import com.njcn.common.utils.wave.BitConverter; +import com.njcn.event.file.pojo.dto.*; +import com.njcn.event.file.pojo.enums.WaveFileResponseEnum; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.io.*; +import java.nio.file.Files; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年03月03日 10:01 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class WaveFileComponent { + + + /****************************************** + * 调用读取comtrate文件方法 + * param strFilePath 波形.cfg文件路径 + * param iType == 0 高级算法的要求,采样率只能是32-128 + * iType == 1 普通展示,采样率按照cfg里面最小的(大于32) + * iType == 2 App抽点要求,采样率抽点成32 + * iType == 3 高级算法原始波形(大于32) + ******************************************/ + public WaveDataDTO getComtrade(InputStream cfgStream, InputStream datStream, int iType) { + WaveDataDTO waveDataDTO = new WaveDataDTO(); + // 首先判断文件路径是否为空 + // 读取cfg文件 + ComtradeCfgDTO comtradeCfgDTO = getComtradeCfg(cfgStream); + // 为空或者未找到结束符号 + if (comtradeCfgDTO == null || !"BINARY".equalsIgnoreCase(comtradeCfgDTO.getStrBinType())) { + return waveDataDTO; + } + /*****根据通道号计算相别** add by yexb -----Start**** + * 1、判断是否是3的倍数,是3的倍数则是3相 + * 2、假如不是3的倍数 ,是1的倍数则是单相 + ********************************************************/ + if (comtradeCfgDTO.getNAnalogNum() % 3 == 0) { + comtradeCfgDTO.setNPhasic(3); + } else { + comtradeCfgDTO.setNPhasic(1); + } + // 给相别幅值 + waveDataDTO.setIPhasic(comtradeCfgDTO.getNPhasic()); + // 组装解析抬头 + List lstWaveTitle = getWaveTitle(comtradeCfgDTO); + // 解析.dat文件 + List> listWaveData = getComtradeDat(comtradeCfgDTO, datStream, iType); + waveDataDTO.setComtradeCfgDTO(comtradeCfgDTO); + waveDataDTO.setWaveTitle(lstWaveTitle); + waveDataDTO.setListWaveData(listWaveData); + //add by hongawen,将暂态触发起始时间记录下来 + waveDataDTO.setTime(DateUtil.format(comtradeCfgDTO.getFirstTime(), DatePattern.NORM_DATETIME_PATTERN).concat(StrPool.DOT)+comtradeCfgDTO.getFirstMs()); + /*****根据通道号计算相别** add by yexb -----end****/ + + return waveDataDTO; + } + + /********************************* + * 根据波形数据算出rms值数据 + * param waveDataDTO 瞬时波形(包含了CFG配置文件) + * List> 返回RMS波形 + **********************************/ + @SuppressWarnings("unused") + public WaveDataDTO getValidData(WaveDataDTO waveDataDTO) { + //CFG 配置文件 + ComtradeCfgDTO comtradeCfgDTO = waveDataDTO.getComtradeCfgDTO(); + //瞬时波形值 + List> lstWave = waveDataDTO.getListWaveData(); + //返回rms的值 + List> listRms = new ArrayList<>(); + /*float fs = nOneWaveNum; + int nWaveNum = (int) nAllWaveNum;*/ + + // 全波有效值 (int)fs / 2;//半波有效值 + int halfTs = comtradeCfgDTO.getFinalSampleRate().intValue(); + // 计算有效值算法 + /********************************* + * modify by yexibao 2020-10-29 + * 增加多波形算法 ---------start + ********************************/ + double iWave; + // 相别 + int nPhasic; + //存放RMS值的最小值 + List> listRmsMin = new ArrayList<>(); + if (lstWave.size() > 0) { + nPhasic = comtradeCfgDTO.getNPhasic(); + //ComtradeCfg.nAnalogNum为值的个数(-1的原因是一个存的是时间) + iWave = Math.floor((lstWave.get(0).size() - 1) / (double) nPhasic); + List tmpListRms; + List tmpListRmsMin; + //增加RMS的最小值 + double fMinTime = 0.0, fMinValue = 0.0; + //每一项一项计算 + for (int j = 0; j < iWave; j++) { + // 实例化 + tmpListRmsMin = new ArrayList<>(); + double fSumA = 0.0, fSumB = 0.0, fSumC = 0.0; + double fValidA, fValidB, fValidC; + //循环原始数据 + for (int i = 0; i < lstWave.size(); i++) { + // 当第一次循环的时候实例化,其余的获取已有的List//获取每一项的值 + List tmpListValue = lstWave.get(i); + if (j == 0) { + tmpListRms = new ArrayList<>(); + //获取时间 + tmpListRms.add(tmpListValue.get(0)); + listRms.add(tmpListRms); + } else { + tmpListRms = listRms.get(i); + } + + //包含了时间、电压(A、B、C)三相、电流(A、B、C)三相 + if (tmpListValue.size() >= 2) { + //电压有效值算法,根据相别进行处理 + switch (comtradeCfgDTO.getNPhasic()) { + case 1: + fSumA += Math.pow(tmpListValue.get(1 + nPhasic * j), 2); + // 计算有效值 + if (i >= halfTs) { + //获取前推周波的值 + List forwardListValue = lstWave.get(i - halfTs); + fSumA -= Math.pow(forwardListValue.get(1 + nPhasic * j), 2); + } + fValidA = Math.sqrt(fSumA / halfTs); + tmpListRms.add((float) (Math.round(fValidA * 100)) / 100); + listRms.set(i, tmpListRms); + // 最小值判断 + if (i >= halfTs) { + if (i == halfTs) { + fMinValue = fValidA; + fMinTime = tmpListValue.get(0); + } else { + if (fValidA < fMinValue) { + fMinValue = fValidA; + fMinTime = tmpListValue.get(0); + } + } + } + break; + case 2: + fSumA += Math.pow(tmpListValue.get(1 + nPhasic * j), 2); + fSumB += Math.pow(tmpListValue.get(2 + nPhasic * j), 2); + // 计算有效值 + if (i >= halfTs) { + //获取前推周波的值 + List forwardListValue = lstWave.get(i - halfTs); + fSumA -= Math.pow(forwardListValue.get(1 + nPhasic * j), 2); + fSumB -= Math.pow(forwardListValue.get(2 + nPhasic * j), 2); + } + fValidA = Math.sqrt(fSumA / halfTs); + fValidB = Math.sqrt(fSumB / halfTs); + + tmpListRms.add((float) (Math.round(fValidA * 100)) / 100); + tmpListRms.add((float) (Math.round(fValidB * 100)) / 100); + listRms.set(i, tmpListRms); + + // 最小值判断 + if (i >= halfTs) { + if (i == halfTs) { + fMinValue = fValidA; + fMinTime = tmpListValue.get(0); + } else { + if (fValidA < fMinValue) { + fMinValue = fValidA; + fMinTime = tmpListValue.get(0); + } + if (fValidB < fMinValue) { + fMinValue = fValidB; + fMinTime = tmpListValue.get(0); + } + } + } + break; + case 3: + fSumA += Math.pow(tmpListValue.get(1 + nPhasic * j), 2); + fSumB += Math.pow(tmpListValue.get(2 + nPhasic * j), 2); + fSumC += Math.pow(tmpListValue.get(3 + nPhasic * j), 2); + // 计算有效值 + if (i >= halfTs) { + //获取前推周波的值 + List forwardListValue = lstWave.get(i - halfTs); + fSumA -= Math.pow(forwardListValue.get(1 + nPhasic * j), 2); + fSumB -= Math.pow(forwardListValue.get(2 + nPhasic * j), 2); + fSumC -= Math.pow(forwardListValue.get(3 + nPhasic * j), 2); + } + fValidA = Math.sqrt(fSumA / halfTs); + fValidB = Math.sqrt(fSumB / halfTs); + fValidC = Math.sqrt(fSumC / halfTs); + + tmpListRms.add((float) (Math.round(fValidA * 100)) / 100); + tmpListRms.add((float) (Math.round(fValidB * 100)) / 100); + tmpListRms.add((float) (Math.round(fValidC * 100)) / 100); + listRms.set(i, tmpListRms); + + // 最小值判断 + if (i >= halfTs) { + if (i == halfTs) { + fMinValue = fValidA; + fMinTime = tmpListValue.get(0); + } else { + if (fValidA < fMinValue) { + fMinValue = fValidA; + fMinTime = tmpListValue.get(0); + } + if (fValidB < fMinValue) { + fMinValue = fValidB; + fMinTime = tmpListValue.get(0); + } + if (fValidC < fMinValue) { + fMinValue = fValidC; + fMinTime = tmpListValue.get(0); + } + } + } + break; + default: + break; + } + } + } + //增加最小值时间,最小值//获取时间 + tmpListRmsMin.add((float) fMinTime); + //获取时间 + tmpListRmsMin.add((float) (Math.round(fMinValue * 100)) / 100); + listRmsMin.add(tmpListRmsMin); + } + + //过滤前一个周波 + //HalfTs表示一个周波 + try { + for (int i = 0; i < halfTs; i++) { + //电压有效值算法 //没相具体的值 + List tmpNewListRms = new ArrayList<>(); + for (int j = 0; j < iWave; j++) { + if (j == 0) { + //获取时间 + tmpNewListRms.add(listRms.get(i).get(0)); + } + switch (nPhasic) { + case 1: + tmpNewListRms.add(listRms.get(i + halfTs).get(1 + nPhasic * j)); + break; + case 2: + tmpNewListRms.add(listRms.get(i + halfTs).get(1 + nPhasic * j)); + tmpNewListRms.add(listRms.get(i + halfTs).get(2 + nPhasic * j)); + break; + case 3: + tmpNewListRms.add(listRms.get(i + halfTs).get(1 + nPhasic * j)); + tmpNewListRms.add(listRms.get(i + halfTs).get(2 + nPhasic * j)); + tmpNewListRms.add(listRms.get(i + halfTs).get(3 + nPhasic * j)); + break; + default: + break; + } + } + //重新赋值 + listRms.set(i, tmpNewListRms); + } + } catch (Exception e) { + throw new BusinessException(WaveFileResponseEnum.RMS_DATA_ERROR); + } + } + waveDataDTO.setListRmsData(listRms); + //RMS最小值 + waveDataDTO.setListRmsMinData(listRmsMin); + + return waveDataDTO; + } + + /***************************** + *获取暂降特征值,包含离线 + * param waveDataDTO 波形返回参数 + * param blType 计算方式 true:浮动门槛 false:固定门槛 + *****************************/ + public List getEigenvalue(WaveDataDTO waveDataDTO, boolean blType) { + //CFG 配置文件 + ComtradeCfgDTO comtradeCfgDTO = waveDataDTO.getComtradeCfgDTO(); + // 瞬时波形值 + List> lstWave = waveDataDTO.getListWaveData(); + //获取最终采样率 + Long finalSampleRate = comtradeCfgDTO.getFinalSampleRate(); + // 返回值 + List lstEigenvalueDTO = new ArrayList<>(); + + // 必须包含了瞬时波形 + if (lstWave.size() > 0) { + MutationDTO mutationDTO = getMutationValue(lstWave, finalSampleRate); + //获取突变量和RMS值 + if (mutationDTO.getListRms_Offline().size() > 0 && mutationDTO.getListTBL_Offline().size() > 0) { + lstEigenvalueDTO = getEventValue(lstWave, mutationDTO, comtradeCfgDTO, blType); + } + } else { + lstEigenvalueDTO = null; + } + return lstEigenvalueDTO; + } + + /*** + * 获取波形文件流,存在则返回inputStream,不存在则返回null + * 为null时,这抛出波形文件不存在异常 + * @author hongawen + * @date 2023/3/3 14:03 + */ + public InputStream getFileInputStreamByFilePath(String filePath) { + File file = new File(filePath); + if (file.isFile() && file.exists()) { + InputStream inputStream; + try { + inputStream = Files.newInputStream(file.toPath()); + if (inputStream.available() < 1) { + throw new BusinessException(WaveFileResponseEnum.WAVE_DATA_INVALID); + } + return inputStream; + } catch (IOException e) { + throw new BusinessException(WaveFileResponseEnum.WAVE_DATA_INVALID); + } + } else { + throw new BusinessException(WaveFileResponseEnum.ANALYSE_WAVE_NOT_FOUND); + } + } + + /********************************* + * 读取cfg方法 + * param strFilePath 文件路径 + * return 返回bool为是否解析出错 + **********************************/ + private ComtradeCfgDTO getComtradeCfg(InputStream cfgStream) { + ComtradeCfgDTO comtradeCfgDTO = new ComtradeCfgDTO(); + InputStreamReader read = null; + BufferedReader bufferedReader = null; + try { + // 将.cfg文件转换为管道流 + read = new InputStreamReader(cfgStream, CharsetUtil.CHARSET_GBK); + bufferedReader = new BufferedReader(read); + //WW 2019-11-14 + float nFreq; + // 第一行不关心仅仅是一些描述类的信息 + String strFileLine = bufferedReader.readLine(); + // 第二行需要关心第二个(模拟量的个数)和第三个参数(开关量的个数) + strFileLine = bufferedReader.readLine(); + // 按“,”进行分割 + String[] strTempArray = strFileLine.split(StrUtil.COMMA); + // 按“,”进行分割 + for (int i = 0; i < strTempArray.length; i++) { + switch (i) { + // 总个数 + case 0: + comtradeCfgDTO.setNChannelNum(Integer.parseInt(strTempArray[i])); + break; + // 模拟量的个数 + case 1: + comtradeCfgDTO.setNAnalogNum(Integer.parseInt(strTempArray[i].substring(0, strTempArray[i].length() - 1))); + break; + // 开关量的个数 + case 2: + comtradeCfgDTO.setNDigitalNum(Integer.parseInt(strTempArray[i].substring(0, strTempArray[i].length() - 1))); + break; + default: + break; + } + } + + // 从第三行到第ComtradeCfg.nChannelNum + 3行是模拟量通道和数字量通道 + List lstAnalogDTO = new ArrayList<>(); + comtradeCfgDTO.setLstAnalogDTO(lstAnalogDTO); + for (int i = 0; i < comtradeCfgDTO.getNChannelNum(); i++) { + AnalogDTO analogDTO = new AnalogDTO(); + lstAnalogDTO.add(analogDTO); + strFileLine = bufferedReader.readLine(); + strTempArray = strFileLine.split(StrUtil.COMMA); + // 配置总共13项 + for (int j = 0; j < strTempArray.length; j++) { + switch (j) { + // 通道序号 + case 0: + analogDTO.setNIndex(Integer.parseInt(strTempArray[j])); + break; + // 通道名称 + case 1: + analogDTO.setSzChannleName(strTempArray[j]); + break; + // 相位名称 + case 2: + analogDTO.setSzPhasicName(strTempArray[j]); + break; + // 监视的通道名称 + case 3: + analogDTO.setSzMonitoredChannleName(strTempArray[j]); + break; + // 通道的单位 + case 4: + analogDTO.setSzUnitName(strTempArray[j]); + break; + // 通道的系数 + case 5: + analogDTO.setFCoefficent(Float.parseFloat(strTempArray[j])); + break; + // 通道的偏移量 + case 6: + analogDTO.setFOffset(Float.parseFloat(strTempArray[j])); + break; + // 起始采样时间的偏移量 + case 7: + analogDTO.setFTimeOffset(Float.parseFloat(strTempArray[j])); + break; + // 采样值的最小值 + case 8: + analogDTO.setNMin(Integer.parseInt(strTempArray[j])); + break; + // 采样值的最大值 + case 9: + analogDTO.setNMax(Integer.parseInt(strTempArray[j])); + break; + // 一次变比 + case 10: + analogDTO.setFPrimary(Float.parseFloat(strTempArray[j])); + break; + // 二次变比 + case 11: + analogDTO.setFSecondary(Float.parseFloat(strTempArray[j])); + break; + // 一次值还是二次值标志 + case 12: + analogDTO.setSzValueType(strTempArray[j]); + break; + default: + break; + } + } + } + //WW 2019-11-14 // 采样频率 + nFreq = Float.parseFloat(bufferedReader.readLine()); + // 获取采样段数 + strFileLine = bufferedReader.readLine(); + int nRates = Integer.parseInt(strFileLine); + comtradeCfgDTO.setNRates(nRates); + // 获得每段的采样率 //采样率 + List lstRate = new ArrayList<>(); + long nOffset = 0; + for (int i = 0; i < nRates; i++) { + strFileLine = bufferedReader.readLine(); + strTempArray = strFileLine.split(StrUtil.COMMA); + RateDTO rateDTO = new RateDTO(); + // 单周波采样点数 //WW 2019-11-14 + rateDTO.setNOneSample((long) (Float.parseFloat(strTempArray[0]) / nFreq)); + // 总点数 //这里的strTemp是一个偏移量 + rateDTO.setNSampleNum((long) (Float.parseFloat(strTempArray[1]) - nOffset)); + lstRate.add(rateDTO); + } + comtradeCfgDTO.setLstRate(lstRate); + // 增加读取波形起始时间个结束时间 + SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss.SSS"); + // 波形起始时间 + strFileLine = bufferedReader.readLine(); + strFileLine = strFileLine.substring(0, strFileLine.length() - 3).replace(StrUtil.COMMA, StrUtil.SPACE); + comtradeCfgDTO.setTimeStart(sdf.parse(strFileLine)); + // 暂态触发时间 + strFileLine = bufferedReader.readLine(); + strFileLine = strFileLine.substring(0, strFileLine.length() - 3).replace(StrUtil.COMMA, StrUtil.SPACE); + comtradeCfgDTO.setTimeTrige(sdf.parse(strFileLine)); + // 获取触发时间的时间 + 毫秒 + Calendar calendar = Calendar.getInstance(); + calendar.setTime(comtradeCfgDTO.getTimeTrige()); + comtradeCfgDTO.setFirstMs(calendar.get(Calendar.MILLISECOND)); + comtradeCfgDTO.setFirstTime(calendar.getTime()); + + long a = comtradeCfgDTO.getTimeStart().getTime(); + long b = comtradeCfgDTO.getTimeTrige().getTime(); + int c = (int) (b - a); + if (c >= 90 && c <= 110) { + comtradeCfgDTO.setNPush(100); + } else if (c >= 190 && c <= 210) { + comtradeCfgDTO.setNPush(200); + } + // 赋值编码格式(二进制) + comtradeCfgDTO.setStrBinType(bufferedReader.readLine().toUpperCase()); + } catch (Exception e) { + // 解析.cfg文件出错 + comtradeCfgDTO = null; + } finally { + try { + bufferedReader.close(); + } catch (IOException e) { + throw new BusinessException(CommonResponseEnum.CLOSE_RESOURCE_ERROR); + } + try { + read.close(); + } catch (IOException e) { + throw new BusinessException(CommonResponseEnum.CLOSE_RESOURCE_ERROR); + } + } + return comtradeCfgDTO; + } + + /********************************* + * 读取dat方法 + * param strFilePath .dat访问路径 + * param strFilePath .dat访问路径 + * param iType 访问波形类型 + * List> 返回波形瞬时值 + **********************************/ + private List> getComtradeDat(ComtradeCfgDTO comtradeCfgDTO, InputStream datStream, int iType) { + //返回数据 + List> listWaveData = new ArrayList<>(); + // 波形文件路径由 .cfg 换成 .dat + //初始化xValue的值 + float xValueAll = 0; + //判断是否首次登陆 + boolean blxValue = false; + byte[] datArray; + try { + datArray = IoUtil.readBytes(datStream); + if (ArrayUtil.isEmpty(datArray)) { + return listWaveData; + } + // 计算每个单独的数据块的大小 4个字节的序号 4个字节的时间 2个字节的值 + // 示例中的排布是 4个字节的序号 4个字节的时间 UA(2字节) UB(2字节) UC(2字节) IA(2字节) IB(2字节) IC(2字节) + int nDigSize = (comtradeCfgDTO.getNDigitalNum() % 16) > 0 ? (comtradeCfgDTO.getNDigitalNum() / 16 + 1) * 2 : comtradeCfgDTO.getNDigitalNum() / 16 * 2; + int nBlockSize = 2 * Integer.SIZE / 8 + comtradeCfgDTO.getNAnalogNum() * 2 + nDigSize; + // 总长度除以每个快的大小 + int nBlockNum = datArray.length / nBlockSize; + // 获取采样率 + long finalSampleRate = getFinalWaveSample(comtradeCfgDTO.getLstRate(), iType); + if (finalSampleRate != -1) { + //设置最终采样率 + comtradeCfgDTO.setFinalSampleRate(finalSampleRate); + // 计算转换后的采样率 + int nnInd = 0; + // 抽点后总共多少点数据 + long nWaveNum; + //抽点后新的的采样率 + List newLstRate = new ArrayList<>(); + for (int iRate = 0; iRate < comtradeCfgDTO.getNRates(); iRate++) { + if (comtradeCfgDTO.getLstRate().get(iRate).getNOneSample() >= 32) { + // 计算本段录波总共有多少波形 + nWaveNum = comtradeCfgDTO.getLstRate().get(iRate).getNSampleNum() / comtradeCfgDTO.getLstRate().get(iRate).getNOneSample(); + //设置总波形大小 + comtradeCfgDTO.setNAllWaveNum(comtradeCfgDTO.getNAllWaveNum() + nWaveNum); + // 将最低采样率替换到本段录波内 + RateDTO tmpRateDTO = new RateDTO(); + newLstRate.add(tmpRateDTO); + //iFlag =3 一定不进行抽点算法 + if (iType != 3) { + //true 抽点算法(当前采样率跟统一采样率不一样则是抽点,否则是未抽点) + if (!Objects.equals(comtradeCfgDTO.getLstRate().get(iRate).getNOneSample(), comtradeCfgDTO.getFinalSampleRate())) { + newLstRate.get(nnInd).setNOneSample(comtradeCfgDTO.getFinalSampleRate()); + // 计算本段录波按照最低采样点应该有多少录波 + newLstRate.get(nnInd).setNSampleNum(comtradeCfgDTO.getFinalSampleRate() * nWaveNum); + } else { + newLstRate.get(nnInd).setNOneSample(comtradeCfgDTO.getLstRate().get(iRate).getNOneSample()); + // 计算本段录波按照最低采样点应该有多少录波 + newLstRate.get(nnInd).setNSampleNum(comtradeCfgDTO.getLstRate().get(iRate).getNOneSample() * nWaveNum); + } + } else { + newLstRate.get(nnInd).setNOneSample(comtradeCfgDTO.getLstRate().get(iRate).getNOneSample()); + // 计算本段录波按照最低采样点应该有多少录波 + newLstRate.get(nnInd).setNSampleNum(comtradeCfgDTO.getLstRate().get(iRate).getNOneSample() * nWaveNum); + } + + // 正常的配置中采样率 + comtradeCfgDTO.getLstRate().get(nnInd).setNOneSample(comtradeCfgDTO.getLstRate().get(iRate).getNOneSample()); + comtradeCfgDTO.getLstRate().get(nnInd).setNSampleNum(comtradeCfgDTO.getLstRate().get(iRate).getNSampleNum()); + nnInd++; + } + } + // 偏移量,采样间隔 + long nOffSet = 0, nWaveSpan; + //两个点之间的时间差 + float fValue, dfValue; + // 计算不同块的采样率 + int nIndex = 0; + // 将最低采样率替换到本段录波内 + // .CFG中采样率 + RateDTO tmpRateDTO; + // nBlockNum 总循环次数 + for (int i = 0; i < nBlockNum; i++) { + tmpRateDTO = comtradeCfgDTO.getLstRate().get(nIndex); + // 计算本段抽点采样间隔 + nWaveSpan = tmpRateDTO.getNOneSample() / newLstRate.get(nIndex).getNOneSample(); + // 判断是否进入下一段 + if (i == tmpRateDTO.getNSampleNum() + nOffSet) { + nOffSet += tmpRateDTO.getNSampleNum(); + nIndex++; + if (nIndex == nnInd) { + break; + } + } + dfValue = (float) 20 / tmpRateDTO.getNOneSample(); + // 判断是否到了需要抽的采样点 + if (i % nWaveSpan == 0) { + // 计算每个通道的值 + //存储局部数据集合,包含了时间,A,B,C三相 + List tmpWaveData = new ArrayList<>(); + AnalogDTO tmpAnalogDTO; + for (int j = 0; j < comtradeCfgDTO.getNAnalogNum(); j++) { + tmpAnalogDTO = comtradeCfgDTO.getLstAnalogDTO().get(j); + //数据只有电压ABC三相数据,不展示U0、I0等数据 YXB2020-10-09 去除相别为N相的数据 + if ("N".equalsIgnoreCase(tmpAnalogDTO.getSzPhasicName())) { + break; + } + float fCoef = tmpAnalogDTO.getFCoefficent(); + fValue = BitConverter.byte2ToUnsignedShort(datArray, i * nBlockSize + 2 * 4 + j * 2) * fCoef; + + //WW 2019-11-14//P是一次值 S是二次值 + if ("S".equalsIgnoreCase(tmpAnalogDTO.getSzValueType())) { + //判断单位是V还是kV + if ("KV".equalsIgnoreCase(tmpAnalogDTO.getSzUnitName())) { + fValue = fValue * 1000.0f; + } + } + //P是一次值 S是二次值 + else if ("P".equalsIgnoreCase(tmpAnalogDTO.getSzValueType())) { + //判断单位是V还是kV + if ("V".equalsIgnoreCase(tmpAnalogDTO.getSzUnitName())) { + //根据cfg内的变比,将一次值转换成二次值 + if (tmpAnalogDTO.getFPrimary() != 0.0f) { + fValue = fValue * tmpAnalogDTO.getFSecondary() / tmpAnalogDTO.getFPrimary(); + } + + } + //判断单位是V还是kV + else if ("KV".equalsIgnoreCase(tmpAnalogDTO.getSzUnitName())) { + //根据cfg内的变比,将一次值转换成二次值 + if (tmpAnalogDTO.getFPrimary() != 0.0f) { + fValue = fValue * 1000.0f * tmpAnalogDTO.getFSecondary() / tmpAnalogDTO.getFPrimary(); + } + } + //还有可能是电流,单位是A + else { + //根据cfg内的变比,将一次值转换成二次值 + if (tmpAnalogDTO.getFPrimary() != 0.0f) { + fValue = tmpAnalogDTO.getFSecondary() / tmpAnalogDTO.getFPrimary(); + } + } + } + + //ComtradeCfg.OneChannleCfg.get(j) + + //xValue前移量,假如是第一次时候则需要前移 + if (!blxValue && j == 0) { + xValueAll = (float) (i * 20) / tmpRateDTO.getNOneSample() - comtradeCfgDTO.getNPush(); + blxValue = true; + //只增加一个xValue的值 //增加时间值 + tmpWaveData.add((float) (Math.round(xValueAll * 100)) / 100); + } else if (j == 0) { + xValueAll += (float) nWaveSpan * dfValue; + //只增加一个xValue的值 //增加时间值 + tmpWaveData.add((float) (Math.round(xValueAll * 100)) / 100); + } + + //不同通道yValue的值都需要增加,最终成ABC三相 //每个通道的值 + tmpWaveData.add((float) (Math.round(fValue * 100)) / 100); + } + //把每个单独的值赋予到整体里面去 + listWaveData.add(tmpWaveData); + } + } + } + } catch (Exception e) { + throw new BusinessException(WaveFileResponseEnum.DAT_DATA_ERROR); + } + + return listWaveData; + } + + + /********************************* + * 获取最小(最终)采样率方法 + * @param lstRate cfg中关于采样率参数 + * @return 返回最小采样率 + **********************************/ + private long getFinalWaveSample(List lstRate, int iType) { + // 最终返回采样率 + long nFinalOneSample = -1; + // 最小采样率 + long nMinOneSample = -1; + if (lstRate.size() > 0) { + nMinOneSample = lstRate.get(0).getNOneSample(); + long tmpOneSample; + for (RateDTO rateDTO : lstRate) { + tmpOneSample = rateDTO.getNOneSample(); + if (tmpOneSample >= 32) { + if (nMinOneSample > tmpOneSample) { + nMinOneSample = tmpOneSample; + } + } + } + } + /******************************************************** + * iFlag == 0 高级算法的要求,采样率只能是32-128 + * iFlag == 1 普通展示,采样率按照cfg里面最小的(大于32) + * iFlag == 2 App抽点要求,采样率抽点成32 + * iFlag == 3 高级算法原始波形(大于32) + ********************************************************/ + switch (iType) { + case 0: + if (nMinOneSample < 32) { + nFinalOneSample = 32; + } else if (nMinOneSample > 128) { + nFinalOneSample = 128; + } + break; + case 2: + nFinalOneSample = 32; + break; + + default: + nFinalOneSample = nMinOneSample; + break; + + } + return nFinalOneSample; + } + + + /********************************* + * 离线波形导入时获取突变量算法 + * param tmpListWave 波形原始数据 + * param finalSampleRate 最终采样率 + **********************************/ + private MutationDTO getMutationValue(List> lstWave, float finalSampleRate) { + MutationDTO mutationDTO = new MutationDTO(); + // 计算有效值 + double fSumA = 0.0, fSumB = 0.0, fSumC = 0.0; + double fValidA, fValidB, fValidC; + double fValue = 0.0; + // 全波有效值 ; (int)fs / 2;//半波有效值 + int HalfTs = (int) finalSampleRate; + //瞬时波形数据_瞬时---前推周波的值_瞬时----周波的值_突变量----前推周波的值_突变量 + List tmpRealValue, forwardRealValue, tblValue, forwardTblValue; + // 计算有效值算法 + for (int i = 0; i < lstWave.size(); i++) { + //获取每一项的值 + tmpRealValue = lstWave.get(i); + //包含了时间、A、B、C三相 + if (tmpRealValue.size() >= 4) { + fSumA += Math.pow(tmpRealValue.get(1), 2); + fSumB += Math.pow(tmpRealValue.get(2), 2); + fSumC += Math.pow(tmpRealValue.get(3), 2); + // 计算有效值 + List tmpRmsValue = new ArrayList<>(); + if (i >= finalSampleRate) { + forwardRealValue = lstWave.get(i - HalfTs); + fSumA -= Math.pow(forwardRealValue.get(1), 2); + fSumB -= Math.pow(forwardRealValue.get(2), 2); + fSumC -= Math.pow(forwardRealValue.get(3), 2); + } + // 计算突变量值 + List tmpTblValue = new ArrayList<>(); + //获取时间 + tmpTblValue.add(tmpRealValue.get(0)); + if (i >= HalfTs) { + //获取前推周波的值 + tblValue = lstWave.get(i); + //获取前推周波的值 + forwardTblValue = lstWave.get(i - HalfTs); + tmpTblValue.add(tblValue.get(1) - forwardTblValue.get(1)); + tmpTblValue.add(tblValue.get(2) - forwardTblValue.get(2)); + tmpTblValue.add(tblValue.get(3) - forwardTblValue.get(3)); + } else { + tmpTblValue.add(0f); + tmpTblValue.add(0f); + tmpTblValue.add(0f); + } + fValidA = Math.sqrt(fSumA / HalfTs); + fValidB = Math.sqrt(fSumB / HalfTs); + fValidC = Math.sqrt(fSumC / HalfTs); + + if (i >= finalSampleRate) { + if (fValidA < mutationDTO.getFMinMagA()) { + mutationDTO.setFMinMagA(fValidA); + } + if (fValidB < mutationDTO.getFMinMagB()) { + mutationDTO.setFMinMagB(fValidB); + } + if (fValidC < mutationDTO.getFMinMagC()) { + mutationDTO.setFMinMagC(fValidC); + } + } + //RMS获取//获取时间 + tmpRmsValue.add(tmpRealValue.get(0)); + tmpRmsValue.add((float) fValidA); + tmpRmsValue.add((float) fValidB); + tmpRmsValue.add((float) fValidC); + mutationDTO.getListRms_Offline().add(tmpRmsValue); + + //RMS获取 + mutationDTO.getListTBL_Offline().add(tmpTblValue); + } + } + return mutationDTO; + } + + /********************************* + * 离线波形导入时获取暂降特征值的算法 + * param lstWave 波形原始数据 + * param tblWave 突变量波形数据 + * param rmstWave RMS数据 + * param comtradeCfgDTO 波形CFG配置参数 + * param blType 计算方式 + * List> 返回暂降数据 + **********************************/ + private List getEventValue(List> lstWave, MutationDTO mutationDTO, ComtradeCfgDTO comtradeCfgDTO, boolean blType) { + List> tblWave = mutationDTO.getListTBL_Offline(); + List> rmstWave = mutationDTO.getListRms_Offline(); + //额定电压 + float fBase = 57.74f; + //假如所选的是380V,那么PT变比是1:1,因此额定电压要选220 //模拟量通道记录 + List lstAnalogDTO = comtradeCfgDTO.getLstAnalogDTO(); + if (!lstAnalogDTO.isEmpty()) { + if (lstAnalogDTO.get(0).getFPrimary() / lstAnalogDTO.get(0).getFSecondary() <= 1) { + fBase = 220f; + } + } + //采样率 + int nSJ = comtradeCfgDTO.getFinalSampleRate().intValue(); + /********************************* + * 0是特征幅值(残余电压百分比) + * 1是特征幅值(残余电压) + * 2额定定压(动态电压) + * 3是持续时间 + **********************************/ + //ABC三相分析结果 + List lstEigenvalueDTO = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + //低电压和郭电压标识值 + int iDDY = 0, iGDY; + //某一项分析结果 + EigenvalueDTO eigenvalueDTO = new EigenvalueDTO(); + iDDY = App_Disturb_DDY1(lstWave, tblWave, rmstWave, nSJ, i, blType); + if (Disturb_Val == 0 && Disturb_SJ == 0) { + //判断A相的暂态事件类型是否为短时中断或电压暂降 + iGDY = App_Disturb_GDY1(lstWave, tblWave, rmstWave, nSJ, i, blType); + if (iGDY != 0) { + if (Disturb_Val != 0) { + if (blType) { + //征幅值(残余电压百分比) + eigenvalueDTO.setAmplitude(Disturb_Val / rmstWave.get(nSJ + 2).get(i + 1)); + //特征幅值(残余电压) + eigenvalueDTO.setResidualVoltage(Disturb_Val); + //额定定压(动态电压) + eigenvalueDTO.setRatedVoltage(rmstWave.get(nSJ + 2).get(i + 1)); + } else { + //征幅值(残余电压百分比) + eigenvalueDTO.setAmplitude(Disturb_Val / 57.74f); + //特征幅值(残余电压) + eigenvalueDTO.setResidualVoltage(Disturb_Val); + //额定定压(动态电压) + eigenvalueDTO.setRatedVoltage(57.74f); + } + } + } + //如果都没有找到,那么需要从曲线里面找出比较小的值来计算 + else { + double rate = 0f; + //残余电压 + double residualVoltage = 0.f; + switch (i) { + case 0: + residualVoltage = mutationDTO.getFMinMagA(); + break; + case 1: + residualVoltage = mutationDTO.getFMinMagB(); + break; + case 2: + residualVoltage = mutationDTO.getFMinMagC(); + break; + default: + break; + } + + if (residualVoltage != -1) { + rate = residualVoltage / fBase > 1 ? 1.0f : residualVoltage / fBase; + } + //征幅值(残余电压百分比) + eigenvalueDTO.setAmplitude((float) rate); + //特征幅值(残余电压) + eigenvalueDTO.setResidualVoltage((float) residualVoltage); + //额定定压(动态电压) + eigenvalueDTO.setRatedVoltage(fBase); + } + } else { + if (Disturb_Val != 0) { + if (blType) { + //征幅值(残余电压百分比) + eigenvalueDTO.setAmplitude(Disturb_Val / rmstWave.get(nSJ + 2).get(i + 1)); + //特征幅值(残余电压) + eigenvalueDTO.setResidualVoltage(Disturb_Val); + //额定定压(动态电压) + eigenvalueDTO.setRatedVoltage(rmstWave.get(nSJ + 2).get(i + 1)); + } else { + //征幅值(残余电压百分比) + eigenvalueDTO.setAmplitude(Disturb_Val / 57.74f); + //特征幅值(残余电压) + eigenvalueDTO.setResidualVoltage(Disturb_Val); + //额定定压(动态电压) + eigenvalueDTO.setRatedVoltage(57.74f); + } + } + } + //持续时间 + eigenvalueDTO.setDurationTime(Disturb_SJ / nSJ * 20.0f); + lstEigenvalueDTO.add(eigenvalueDTO); + } + return lstEigenvalueDTO; + } + + /*** + * 暂降幅值 + */ + private float Disturb_Val = 0; + /*** + * 持续时间 + */ + private double Disturb_Time = 0; + /*** + * 暂态启动点号 + */ + private float Disturb_SJ = 0; + + /*** + * 暂降幅值90% + */ + private float Un09 = (0.90f * 57.74f); + /*** + * 暂降幅值2% + */ + private float Un002 = (0.02f * 57.74f); + /*** + * 暂降幅值110% + */ + private float Un110 = (1.10f * 57.74f); + + /************************************ + *低电压的判据 包含了暂降和中断 + * @param realWave 原始波形数据 + * @param tblWave 突变量波形数据 + * @param rmstWave RMS波形数据 + * @param nCirclePoint 采样率 + * @param nType 类别 0:A相,1:B相,2:C相 + * @param blFlag 浮动门槛和固定门槛 + *************************************/ + private int App_Disturb_DDY1(List> realWave, List> tblWave, List> rmstWave, int nCirclePoint, int nType, boolean blFlag) { + Disturb_Val = 0; + Disturb_Time = 0; + Disturb_SJ = 0; + + /**************************** + * ADC 临时的突变量判据 + * Disturb_JS_Val 事件启动点时刻的有效值 + ****************************/ + double temp, ADC, Disturb_JS_Val = 0; + int iTbl = 0; + long Disturb_QD = 0; + //nSJ就是全波的采样率,nHalfSJ是半波的采样率 + int nSJ = nCirclePoint, nHalfSJ = nCirclePoint / 2; + //定义90%和20%额定电压 + float fUN09 = Un09, fUN002 = Un002; + //增加浮动门槛判断 + if (blFlag) { + /**************************** + * 计算值去掉一个前一个周波后 + * 取第二个周波的第二个有效值 + * 第一个值是时间、A,B,C三相 + ****************************/ + if (rmstWave.size() > nSJ + 2) { + fUN09 = rmstWave.get(nSJ + 2).get(nType + 1) * 0.9f; + fUN002 = rmstWave.get(nSJ + 2).get(nType + 1) * 0.02f; + } + } + /**************************** + * 从第二个周波开始 + ****************************/ + for (int i = nSJ; i < realWave.size(); i++) { + //获取RMS有效值 + float rmsValue = rmstWave.get(i).get(nType + 1); + //电压扰动启动判别 + if (Disturb_QD == 0) { + //有效值小于90% + if (rmsValue < fUN09) { + Disturb_QD = 0xff; + Disturb_Val = rmsValue; + Disturb_JS_Val = rmsValue; + //寻找突变点 + for (int j = 0; j < nHalfSJ; j++) { + //临时的突变量 + ADC = tblWave.get(i - nHalfSJ + j).get(nType + 1); + //临时的突变量小于0的时候取绝对值 + if (ADC < 0) { + ADC = 0 - ADC; + } + if (ADC > fUN002) { + Disturb_SJ += (nHalfSJ - j); + iTbl = (i - nHalfSJ + j); + break; + } + } + } + } + //电压扰动返回判别 + else { + if (rmsValue < (fUN09 + fUN002)) { + Disturb_SJ++; + if (Disturb_Val > rmsValue) { + Disturb_Val = rmsValue; + } + Disturb_JS_Val = rmsValue; + } else { + if (Disturb_SJ >= (nSJ + nHalfSJ)) { + //20%突变量标志 + int iFlag = 0; + for (int j = 0; j < nHalfSJ; j++) { + iFlag = j; + //临时的突变量 + ADC = tblWave.get(i - nHalfSJ + j).get(nType + 1); + //临时的突变量小于0的时候取绝对值 + if (ADC < 0) { + ADC = 0 - ADC; + } + if (ADC > fUN002) { + break; + } + } + Disturb_SJ -= (nHalfSJ - iFlag); + Disturb_Time = ((double) Disturb_SJ) * 20 / nSJ; + return iTbl; + } else { + Disturb_SJ++; + ADC = realWave.get(i).get(nType + 1); + if (ADC < 0) { + ADC = 0 - ADC; + } + temp = rmsValue - Disturb_JS_Val; + if (temp < 0) { + temp = 0 - temp; + } + if ((ADC > 100) && (temp < 0.1)) { + Disturb_SJ -= (nHalfSJ + 1); + Disturb_Time = ((double) Disturb_SJ) * 20 / nSJ + 1; + return iTbl; + } + } + Disturb_JS_Val = rmsValue; + } + } + } + return iTbl; + } + + + /************************************ + *过电压的判据 + * @param realWave 原始波形数据 + * @param tblWave 突变量波形数据 + * @param rmstWave RMS波形数据 + * @param nCirclePoint 采样率 + * @param nType 类别 0:A相,1:B相,2:C相 + * @param blFlag 浮动门槛和固定门槛 + * @return + *************************************/ + private int App_Disturb_GDY1(List> realWave, List> tblWave, List> rmstWave, int nCirclePoint, int nType, boolean blFlag) { + Disturb_Val = 0; + Disturb_Time = 0; + Disturb_SJ = 0; + + /**************************** + * ADC 临时的突变量判据 + * Disturb_JS_Val 事件启动点时刻的有效值 + ****************************/ + double temp, ADC, Disturb_JS_Val = 0; + int iTbl = 0; + long Disturb_QD = 0; + //nSJ就是全波的采样率,nHalfSJ是半波的采样率 + int nSJ = nCirclePoint, nHalfSJ = nCirclePoint / 2; + //定义110%和20%额定电压 + float fUN110 = Un110, fUN002 = Un002; + //增加浮动门槛判断 + if (blFlag) { + /**************************** + * 计算值去掉一个前一个周波后 + * 取第二个周波的第二个有效值 + * 第一个值是时间、A,B,C三相 + ****************************/ + if (rmstWave.size() > nSJ + 2) { + fUN110 = rmstWave.get(nSJ + 2).get(nType + 1) * 1.1f; + fUN002 = rmstWave.get(nSJ + 2).get(nType + 1) * 0.02f; + } + } + /**************************** + * 从第二个周波开始 + ****************************/ + for (int i = nSJ; i < realWave.size(); i++) { + //获取RMS有效值 + float rmsValue = rmstWave.get(i).get(nType + 1); + //电压扰动启动判别 + if (Disturb_QD == 0) { + if (rmsValue > fUN110) { + Disturb_QD = 0xff; + Disturb_Val = rmsValue; + Disturb_JS_Val = rmsValue; + //寻找突变点 + for (int j = 0; j < nHalfSJ; j++) { + //临时的突变量 + ADC = tblWave.get(i - nHalfSJ + j).get(nType + 1); + //临时的突变量小于0时候取绝对值 + if (ADC < 0) { + ADC = 0 - ADC; + } + if (ADC > fUN002) { + Disturb_SJ += (nHalfSJ - j); + iTbl = (int) (i - nHalfSJ + j); + break; + } + } + } + } + //电压扰动返回判别 + else { + if (rmsValue > (fUN110 - fUN002)) { + Disturb_SJ++; + if (Disturb_Val < rmsValue) { + Disturb_Val = rmsValue; + } + Disturb_JS_Val = rmsValue; + } else { + if (Disturb_SJ >= (nSJ + nHalfSJ)) { + int iFlag = 0; + for (int j = 0; j < nHalfSJ; j++) { + iFlag = j; + ADC = tblWave.get(i - nHalfSJ + j).get(nType + 1); + if (ADC < 0) { + ADC = 0 - ADC; + } + if (ADC > fUN002) { + break; + } + } + Disturb_SJ -= (nHalfSJ - iFlag); + Disturb_Time = (double) Disturb_SJ * 20 / nSJ; + return iTbl; + } else { + Disturb_SJ++; + ADC = realWave.get(i).get(nType + 1); + if (ADC < 0) { + ADC = 0 - ADC; + } + temp = rmsValue - Disturb_JS_Val; + if (temp < 0) { + temp = 0 - temp; + } + if ((ADC > 100) && (temp < 0.1)) { + Disturb_SJ -= (nHalfSJ + 1); + Disturb_Time = Disturb_SJ * 20 / nSJ + 1; + return iTbl; + } + } + Disturb_JS_Val = rmsValue; + } + } + } + return iTbl; + } + + + /********************************* + * 获取波形标题的方法 + * param tmpComtradeCfgDTO 文件路径 + * return 返回List返回数据格式说明 + **********************************/ + private List getWaveTitle(ComtradeCfgDTO comtradeCfgDTO) { + //编辑数据标题 YXB2020-10-09 去除相别为N相的数据//存储数据标题 + List tmpWaveTitle = new ArrayList<>(); + // 模拟量通道记录类 + AnalogDTO analogDTO; + tmpWaveTitle.add("Time"); + String strUnit; + for (int j = 0; j < comtradeCfgDTO.getNAnalogNum(); j++) { + analogDTO = comtradeCfgDTO.getLstAnalogDTO().get(j); + // 假如为N相则跳过 + if (!StrUtil.equals(analogDTO.getSzPhasicName().toUpperCase(), "N")) { + if ("A".equalsIgnoreCase(analogDTO.getSzUnitName())) { + strUnit = "I"; + } else { + strUnit = "U"; + } + tmpWaveTitle.add(strUnit + analogDTO.getSzPhasicName().toUpperCase() + "相"); + } + } + return tmpWaveTitle; + } + + /********************************* + * 由.cfg 路径更换成 .dat + * param strFilePath 文件路径 + * return String返回.dat文件的路径 + **********************************/ + private String getDatFilePath(String strFilePath) { + String strDatFilePath; + //替换前的 + String strOriginally = ".cfg"; + //替换后的 + String strReplace = ".dat"; + //截取.之后字符串 + String strIntercept = strFilePath.substring(strFilePath.lastIndexOf(".") + 1); + switch (strIntercept) { + case "cfg": + strOriginally = ".cfg"; + strReplace = ".dat"; + break; + case "CFG": + strOriginally = ".CFG"; + strReplace = ".DAT"; + break; + case "Cfg": + strOriginally = ".Cfg"; + strReplace = ".Dat"; + break; + case "CFg": + strOriginally = ".CFg"; + strReplace = ".DAt"; + break; + case "cFg": + strOriginally = ".cFg"; + strReplace = ".dAt"; + break; + case "cFG": + strOriginally = ".cFG"; + strReplace = ".dAT"; + break; + default: + break; + } + //把.cfg换成.dat + strDatFilePath = strFilePath.replace(strOriginally, strReplace); + return strDatFilePath; + } + + public static void main(String[] args) { + /******************************************************** + * iFlag == 0 高级算法的要求,采样率只能是32-128 + * iFlag == 1 普通展示,采样率按照cfg里面最小的(大于32) + * iFlag == 2 App抽点要求,采样率抽点成32 + * iFlag == 3 高级算法原始波形(大于32) + ********************************************************/ + /** 输出格式: 2014-5-05 00:00:00 大写H为24小时制 */ + DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String s; + Date d = new Date(); + s = sdf.format(d); + System.out.println(s); + WaveFileComponent waveFileComponent = new WaveFileComponent(); + InputStream cfgStream = waveFileComponent.getFileInputStreamByFilePath("D:\\comtrade\\00-B7-8D-00-B7-25\\1_20200629_164016_234.CFG"); + InputStream datStream = waveFileComponent.getFileInputStreamByFilePath("D:\\comtrade\\00-B7-8D-00-B7-25\\1_20200629_164016_234.DAT"); + // 获取瞬时波形 //获取原始波形值 + WaveDataDTO waveDataDTO = waveFileComponent.getComtrade(cfgStream,datStream, 1); + d = new Date(); + s = sdf.format(d); + System.out.println(s); + // 获取RMS波形 + WaveDataDTO waveDataDTO1 = waveFileComponent.getValidData(waveDataDTO); + d = new Date(); + s = sdf.format(d); + System.out.println(s); + // 获取特征值 + List lstEigenvalueDTO = waveFileComponent.getEigenvalue(waveDataDTO, true); + } + +} diff --git a/pqs-common/common-event/src/main/java/com/njcn/event/file/component/WavePicComponent.java b/pqs-common/common-event/src/main/java/com/njcn/event/file/component/WavePicComponent.java new file mode 100644 index 000000000..db527e2d6 --- /dev/null +++ b/pqs-common/common-event/src/main/java/com/njcn/event/file/component/WavePicComponent.java @@ -0,0 +1,152 @@ +package com.njcn.event.file.component; + +import cn.hutool.core.img.ImgUtil; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.CharsetUtil; +import com.njcn.common.pojo.exception.BusinessException; +import com.njcn.common.utils.FileUtil; +import com.njcn.echarts.util.DrawPicUtil; +import com.njcn.event.file.pojo.bo.WaveDataDetail; +import com.njcn.event.file.pojo.dto.WaveDataDTO; +import com.njcn.event.file.pojo.enums.WaveFileResponseEnum; +import com.njcn.oss.constant.OssPath; +import com.njcn.oss.utils.FileStorageUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import sun.awt.image.BufferedImageGraphicsConfig; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Base64; +import java.util.List; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年09月21日 09:18 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class WavePicComponent { + + private final DrawPicUtil drawPicUtil; + + private final FileStorageUtil fileStorageUtil; + + /*** + * 绘制瞬时波形图 + * @author hongawen + * @date 2023/9/21 15:32 + * @return String 文件地址 + */ + public String generateImageShun(WaveDataDTO waveDataDTO, List waveDataDetails) { + String picPath = null; + String time = waveDataDTO.getTime(); + String title = "监测点名称:" + waveDataDTO.getMonitorName() + " 发生时刻:" + time; + WaveDataDetail waveDataDetail = waveDataDetails.get(0); + String firstPic = drawPicUtil.drawWavePic(title, waveDataDetail.getInstantData().getAValue(), + waveDataDetail.getInstantData().getBValue(), waveDataDetail.getInstantData().getCValue(), + waveDataDetail.getUnit(), waveDataDetail.getInstantData().getMax(), waveDataDetail.getInstantData().getMin(), + waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(), + waveDataDetail.getColors(), waveDataDetail.getIsOpen() + ); + String secondPic; + if (waveDataDetails.size() == 1) { + //将图片上传到minioss + InputStream instantStream = IoUtil.toStream(firstPic, CharsetUtil.UTF_8); + picPath = fileStorageUtil.uploadStream(instantStream, OssPath.EVENT_WAVE_PIC, FileUtil.generateFileName("png")); + } else if (waveDataDetails.size() == 2) { + //绘制第二个电压瞬时波形图 + waveDataDetail = waveDataDetails.get(1); + secondPic = drawPicUtil.drawWavePic("", waveDataDetail.getInstantData().getAValue(), + waveDataDetail.getInstantData().getBValue(), waveDataDetail.getInstantData().getCValue(), + waveDataDetail.getUnit(), waveDataDetail.getInstantData().getMax(), waveDataDetail.getInstantData().getMin(), + waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(), + waveDataDetail.getColors(), waveDataDetail.getIsOpen() + ); + picPath = composeImage(firstPic, secondPic); + } + return picPath; + } + + /*** + * 绘制RMS波形图 + * @author hongawen + * @date 2023/9/21 15:32 + * @return String 文件地址 + */ + public String generateImageRms(WaveDataDTO waveDataDTO, List waveDataDetails) { + String picPath = null; + String time = waveDataDTO.getTime(); + String title = "监测点名称:" + waveDataDTO.getMonitorName() + " 发生时刻:" + time; + WaveDataDetail waveDataDetail = waveDataDetails.get(0); + String firstPic = drawPicUtil.drawWavePic(title, waveDataDetail.getRmsData().getAValue(), + waveDataDetail.getRmsData().getBValue(), waveDataDetail.getRmsData().getCValue(), + waveDataDetail.getUnit(), waveDataDetail.getRmsData().getMax(), waveDataDetail.getRmsData().getMin(), + waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(), + waveDataDetail.getColors(), waveDataDetail.getIsOpen() + ); + String secondPic; + if (waveDataDetails.size() == 1) { + //将图片上传到minioss + InputStream instantStream = IoUtil.toStream(firstPic, CharsetUtil.UTF_8); + picPath = fileStorageUtil.uploadStream(instantStream, OssPath.EVENT_WAVE_PIC, FileUtil.generateFileName("png")); + } else if (waveDataDetails.size() == 2) { + //绘制第二个电压瞬时波形图 + waveDataDetail = waveDataDetails.get(1); + secondPic = drawPicUtil.drawWavePic("", waveDataDetail.getRmsData().getAValue(), + waveDataDetail.getRmsData().getBValue(), waveDataDetail.getRmsData().getCValue(), + waveDataDetail.getUnit(), waveDataDetail.getRmsData().getMax(), waveDataDetail.getRmsData().getMin(), + waveDataDetail.getA(), waveDataDetail.getB(), waveDataDetail.getC(), + waveDataDetail.getColors(), waveDataDetail.getIsOpen() + ); + picPath = composeImage(firstPic, secondPic); + } + return picPath; + } + + /*** + * 合成图片 + * @author hongawen + * @date 2023/9/21 15:33 + * @param firstPic 第一张图 + * @param secondPic 第二张图 + * @return String + */ + private String composeImage(String firstPic, String secondPic) { + try { + //第一张图片 base64截取删除前缀data:image/png;base64, + BufferedImage imageOne = ImgUtil.toBufferedImage(ImgUtil.toImage(firstPic.substring(22)), ImgUtil.IMAGE_TYPE_PNG); + int width = imageOne.getWidth(); + int height = imageOne.getHeight(); + int[] imageArrayOne = new int[width * height]; + imageArrayOne = imageOne.getRGB(0, 0, width, height, imageArrayOne, 0, width); + //第二张图片 base64截取删除前缀data:image/png;base64, + BufferedImage imageTwo = ImgUtil.toBufferedImage(ImgUtil.toImage(secondPic.substring(22)), ImgUtil.IMAGE_TYPE_PNG); + int width2 = imageTwo.getWidth(); + int height2 = imageTwo.getHeight(); + int[] ImageArrayTwo = new int[width2 * height2]; + ImageArrayTwo = imageTwo.getRGB(0, 0, width, height, ImageArrayTwo, 0, width); + //新图片 + BufferedImage imageNew = new BufferedImage(width, height * 2, BufferedImage.TYPE_INT_RGB); + BufferedImageGraphicsConfig config = BufferedImageGraphicsConfig.getConfig(imageNew); + imageNew = config.createCompatibleImage(width, height * 2, Transparency.TRANSLUCENT); + imageNew.setRGB(0, 0, width, height, imageArrayOne, 0, width); + imageNew.setRGB(0, height, width, height, ImageArrayTwo, 0, width); + String resultImg = ImgUtil.toBase64(imageNew, ImgUtil.IMAGE_TYPE_PNG); + byte[] bytes = Base64.getDecoder().decode(resultImg); + return fileStorageUtil.uploadStream(new ByteArrayInputStream(bytes), OssPath.EVENT_WAVE_PIC, FileUtil.generateFileName("png")); + } catch (Exception e) { + throw new BusinessException(WaveFileResponseEnum.COMPOSE_PIC_ERROR); + } + } + + +} diff --git a/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/bo/InstantData.java b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/bo/InstantData.java new file mode 100644 index 000000000..b7b47757e --- /dev/null +++ b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/bo/InstantData.java @@ -0,0 +1,25 @@ +package com.njcn.event.file.pojo.bo; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年09月20日 16:11 + */ +@Data +public class InstantData { + + private Float max; + + private Float min; + + List> aValue =new ArrayList<>(); + + List> bValue =new ArrayList<>(); + + List> cValue =new ArrayList<>(); +} diff --git a/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/bo/RmsData.java b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/bo/RmsData.java new file mode 100644 index 000000000..444118126 --- /dev/null +++ b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/bo/RmsData.java @@ -0,0 +1,25 @@ +package com.njcn.event.file.pojo.bo; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年09月20日 16:12 + */ +@Data +public class RmsData { + + private Float max; + + private Float min; + + List> aValue =new ArrayList<>(); + + List> bValue =new ArrayList<>(); + + List> cValue =new ArrayList<>(); +} diff --git a/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/bo/WaveDataDetail.java b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/bo/WaveDataDetail.java new file mode 100644 index 000000000..4ade35362 --- /dev/null +++ b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/bo/WaveDataDetail.java @@ -0,0 +1,33 @@ +package com.njcn.event.file.pojo.bo; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年09月20日 16:13 + */ +@Data +public class WaveDataDetail { + + private InstantData instantData; + + private RmsData rmsData; + + private String a ="A相"; + + private String b ="B相"; + + private String c ="C相"; + + private String unit; + + private Boolean isOpen = false; + + private String title; + + private List colors= new ArrayList<>(); +} diff --git a/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/AnalogDTO.java b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/AnalogDTO.java new file mode 100644 index 000000000..127b83c1c --- /dev/null +++ b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/AnalogDTO.java @@ -0,0 +1,46 @@ +package com.njcn.event.file.pojo.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @author yxb + * @version 1.0.0 + * @date 2022年06月02日 20:03 + * 模拟量通道记录类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class AnalogDTO implements Serializable { + + // 通道序号 + private Integer nIndex; + // 通道名称 + private String szChannleName; + // 相位名称 + private String szPhasicName; + // 监视的通道名称 + private String szMonitoredChannleName; + // 通道的单位 + private String szUnitName; + // 通道的系数 + private Float fCoefficent; + // 通道的便宜量 + private Float fOffset; + // 起始采样时间的偏移量 + private Float fTimeOffset; + // 采样值的最小值 + private Integer nMin; + // 采样值的最大值 + private Integer nMax; + // 一次变比 + private Float fPrimary; + // 二次变比 + private Float fSecondary; + // 一次值还是二次值标志 + private String szValueType; +} diff --git a/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/ComtradeCfgDTO.java b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/ComtradeCfgDTO.java new file mode 100644 index 000000000..185ba122f --- /dev/null +++ b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/ComtradeCfgDTO.java @@ -0,0 +1,50 @@ +package com.njcn.event.file.pojo.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * @author yxb + * @version 1.0.0 + * @date 2022年06月02日 20:03 + * CFG配置文件总类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ComtradeCfgDTO implements Serializable { + private Integer nChannelNum; + private Integer nPhasic;// 模拟量通道的个数 yxb 2020-12-15 + private Integer nAnalogNum;// 模拟量通道的个数 WW 2013-05-15 + private Integer nDigitalNum;// 数字量通道的个数 WW 2013-05-15 + private Date timeStart;// 暂态记录时间 yxb 2022-06-06 + private Date timeTrige;// 暂态触发时间 yxb 2022-06-06 + + private List lstAnalogDTO;//模拟量通道记录 + private List lstDigitalDTO;//数字量通道记录 + + public Integer nRates;//对应采样次数 + public List lstRate;//采样率合集 + + // add by sw 暂降触发时间 + private Date firstTime; // 暂降触发第一次 + private Integer firstMs; // 暂降触发第一次毫秒 + + // 波形前推周波束 + private Integer nPush = 0; + // 最终采样率,计算的时候只用一个采样率 + private Long finalSampleRate; + // 整个波形大小 + private Long nAllWaveNum = 0L; + + /*** + * 赋值编码格式(二进制) + */ + private String strBinType; + +} diff --git a/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/DigitalDTO.java b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/DigitalDTO.java new file mode 100644 index 000000000..ab0350adf --- /dev/null +++ b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/DigitalDTO.java @@ -0,0 +1,30 @@ +package com.njcn.event.file.pojo.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @author yxb + * @version 1.0.0 + * @date 2022年06月02日 20:03 + * 数字量通道记录类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class DigitalDTO implements Serializable { + + // 通道序号 + private Integer nIndex; + // 通道名称 + private String szChannleName; + // 相位名称 + private String szPhasicName; + // 监视的通道名称 + private String szMonitoredChannleName; + // 通道的单位 + private Integer Initial; +} diff --git a/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/EigenvalueDTO.java b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/EigenvalueDTO.java new file mode 100644 index 000000000..f082491e9 --- /dev/null +++ b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/EigenvalueDTO.java @@ -0,0 +1,28 @@ +package com.njcn.event.file.pojo.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @author yxb + * @version 1.0.0 + * @date 2022年06月02日 20:03 + * 特征值计算类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class EigenvalueDTO implements Serializable { + + //是特征幅值(残余电压百分比) + private float amplitude; + //是特征幅值(残余电压) + private float residualVoltage; + //额定定压(动态电压) + private float ratedVoltage; + //持续时间 + private float durationTime; +} diff --git a/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/MutationDTO.java b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/MutationDTO.java new file mode 100644 index 000000000..9ef8ae947 --- /dev/null +++ b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/MutationDTO.java @@ -0,0 +1,27 @@ +package com.njcn.event.file.pojo.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * @author yxb + * @version 1.0.0 + * @date 2022年06月02日 20:03 + * 突变量计算类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class MutationDTO implements Serializable { + + private List> listRms_Offline = new ArrayList<>();//离线数据RMS有效值数据 + private List> listTBL_Offline = new ArrayList<>();//离线数据突变量数据 + private double fMinMagA = 99999d; + private double fMinMagB = 99999d; + private double fMinMagC = 99999d; +} diff --git a/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/RateDTO.java b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/RateDTO.java new file mode 100644 index 000000000..169428e09 --- /dev/null +++ b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/RateDTO.java @@ -0,0 +1,24 @@ +package com.njcn.event.file.pojo.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * @author yxb + * @version 1.0.0 + * @date 2022年06月02日 20:03 + * 采样率类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RateDTO implements Serializable { + + // 1秒钟内的采样点数 + private Long nOneSample; + // 总采样点数 + private Long nSampleNum; +} diff --git a/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/WaveDataDTO.java b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/WaveDataDTO.java new file mode 100644 index 000000000..2854c939a --- /dev/null +++ b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/dto/WaveDataDTO.java @@ -0,0 +1,44 @@ +package com.njcn.event.file.pojo.dto; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * @author yxb + * @version 1.0.0 + * @date 2022年06月02日 20:03 + * 返回波形数据类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class WaveDataDTO implements Serializable { + + //CFG实体类 + private ComtradeCfgDTO comtradeCfgDTO; + //波形对应的标题 + private List waveTitle; + //波形对应的值 + private List> listWaveData; + //波形RMS值 + private List> listRmsData; + //RMS最小值 + private List> listRmsMinData; + //波形对应的相别数量 + private Integer iPhasic; + //接线方式(0.星型接法;1.三角型接法;2.开口三角型接法) + private Integer ptType; + //PT变比 + private Double pt; + //CT变比" + private Double ct; + //暂降发生时刻 + private String time; + //测点名称 + private String monitorName; +} diff --git a/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/enums/WaveFileResponseEnum.java b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/enums/WaveFileResponseEnum.java new file mode 100644 index 000000000..a59138b21 --- /dev/null +++ b/pqs-common/common-event/src/main/java/com/njcn/event/file/pojo/enums/WaveFileResponseEnum.java @@ -0,0 +1,33 @@ +package com.njcn.event.file.pojo.enums; + +import lombok.Getter; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2021年12月20日 09:56 + */ +@Getter +public enum WaveFileResponseEnum { + + /** + * 暂降模块异常响应码的范围: + * A00650 ~ A00749 + */ + EVENT_NOT_FOUND("A00651","暂降事件或监测点不存在"), + ANALYSE_WAVE_NOT_FOUND("A00652","波形文件找不到"), + WAVE_DATA_INVALID("A00654","波形文件数据缺失"), + DAT_DATA_ERROR("A00653","dat文件数据读取失败"), + RMS_DATA_ERROR("A00653","rms数据读取失败"), + COMPOSE_PIC_ERROR("A00653","合成波形图失败"), + ; + + private final String code; + + private final String message; + + WaveFileResponseEnum(String code, String message) { + this.code = code; + this.message = message; + } +} diff --git a/pqs-common/common-event/src/main/java/com/njcn/event/file/utils/WaveUtil.java b/pqs-common/common-event/src/main/java/com/njcn/event/file/utils/WaveUtil.java new file mode 100644 index 000000000..dcd6a170a --- /dev/null +++ b/pqs-common/common-event/src/main/java/com/njcn/event/file/utils/WaveUtil.java @@ -0,0 +1,189 @@ +package com.njcn.event.file.utils; + +import com.njcn.event.file.pojo.bo.InstantData; +import com.njcn.event.file.pojo.bo.RmsData; +import com.njcn.event.file.pojo.bo.WaveDataDetail; +import com.njcn.event.file.pojo.dto.WaveDataDTO; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年09月20日 16:14 + */ +public class WaveUtil { + + /** + * 筛选后台绘图所需的瞬时、RMS等一次值数据 + */ + public static List filterWaveData(WaveDataDTO waveDataDTO) { + List waveDataDetails = new ArrayList<>(); + List waveTitle = waveDataDTO.getWaveTitle(); + boolean openTri = waveDataDTO.getPtType() == 2; + /************ 一个图形的相别决定了图形个数 Modify by yexb -----start ***********/ + Integer iPhase = waveDataDTO.getIPhasic(); + int picCounts = (waveTitle.size() - 1) / iPhase; + /**处理相别的颜色**/ + List colors = new ArrayList<>(); + //遍历图形个数 + for (int i = 0; i < picCounts; i++) { + WaveDataDetail waveDataDetail = new WaveDataDetail(); + switch (iPhase) { + case 1: + waveDataDetail.setA(waveTitle.get(i + 1).substring(1)); + waveDataDetail.setB(""); + waveDataDetail.setC(""); + colors.add("#DAA520"); + colors.add("#fff"); + colors.add("#fff"); + break; + case 2: + waveDataDetail.setA(waveTitle.get(i * 2 + 1).substring(1)); + waveDataDetail.setB(waveTitle.get(i * 2 + 2).substring(1)); + waveDataDetail.setC(""); + colors.add("#DAA520"); + colors.add("#2E8B57"); + colors.add("#fff"); + break; + case 3: + waveDataDetail.setA(waveTitle.get(i * 3 + 1).substring(1)); + waveDataDetail.setB(waveTitle.get(i * 3 + 2).substring(1)); + waveDataDetail.setC(waveTitle.get(i * 3 + 3).substring(1)); + colors.add("#DAA520"); + colors.add("#2E8B57"); + colors.add("#A52a2a"); + break; + } + waveDataDetail.setColors(colors); + + float xishu = waveDataDTO.getPt().floatValue(); + if (waveTitle.get(iPhase * i + 1).substring(0, 1).equalsIgnoreCase("U")) { + waveDataDetail.setUnit("kV"); + xishu = xishu / 1000; + } else { + waveDataDetail.setUnit("A"); + xishu = waveDataDTO.getCt().floatValue(); + } + Float sfMax = 0f, sfMin = 0f, rfMax = 0f, rfMin = 0f; + List> sAValue = new ArrayList<>(), sBValue = new ArrayList<>(), sCValue = new ArrayList<>(), rAValue = new ArrayList<>(), rBValue = new ArrayList<>(), rCValue = new ArrayList<>(); + List> sunData = waveDataDTO.getListWaveData(); + for (int j = 0; j < sunData.size(); j++) { + float x = sunData.get(j).get(0); + float shunFirstA = 0f, shunFirstB = 0f, shunFirstC = 0f; + //根据相别来确认标题的名称 + for (int m = 0; m < iPhase; m++) { + if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("A")) { + float tmpShunFirstA = sunData.get(j).get(iPhase * i + m + 1) * xishu; + shunFirstA = tmpShunFirstA; + sAValue.add(new ArrayList() {{ + add(x); + add(tmpShunFirstA); + }}); + } + if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("B")) { + float tmpShunFirstB = sunData.get(j).get(iPhase * i + m + 1) * xishu; + shunFirstB = tmpShunFirstB; + sBValue.add(new ArrayList() {{ + add(x); + add(tmpShunFirstB); + }}); + } + if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("C")) { + float tmpShunFirstC = sunData.get(j).get(iPhase * i + m + 1) * xishu; + shunFirstC = tmpShunFirstC; + sCValue.add(new ArrayList() {{ + add(x); + add(tmpShunFirstC); + }}); + } + } + sfMax = getMax(sfMax, shunFirstA, shunFirstB, shunFirstC); + if (openTri) { + sfMin = getMinOpen(sfMin, shunFirstA, shunFirstC); + } else { + sfMin = getMin(sfMin, shunFirstA, shunFirstB, shunFirstC); + } + } + InstantData instantData = new InstantData(); + instantData.setAValue(sAValue); + instantData.setBValue(sBValue); + instantData.setCValue(sCValue); + instantData.setMax(sfMax); + instantData.setMin(sfMin); + List> rmsData = waveDataDTO.getListRmsData(); + for (int k = 0; k < rmsData.size(); k++) { + float x = rmsData.get(k).get(0); + float rmsFirstA = 0f, rmsFirstB = 0f, rmsFirstC = 0f; + //根据相别来确认标题的名称 + for (int m = 0; m < iPhase; m++) { + if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("A")) { + float tmpRmsFirstA = rmsData.get(k).get(iPhase * i + m + 1) * xishu; + rmsFirstA = tmpRmsFirstA; + rAValue.add(new ArrayList() {{ + add(x); + add(tmpRmsFirstA); + }}); + } + if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("B")) { + float tmpRmsFirstB = rmsData.get(k).get(iPhase * i + m + 1) * xishu; + rmsFirstB = tmpRmsFirstB; + rBValue.add(new ArrayList() {{ + add(x); + add(tmpRmsFirstB); + }}); + } + if (waveTitle.get(iPhase * i + m + 1).substring(1).contains("C")) { + float tmpRmsFirstC = rmsData.get(k).get(iPhase * i + m + 1) * xishu; + rmsFirstC = tmpRmsFirstC; + rCValue.add(new ArrayList() {{ + add(x); + add(tmpRmsFirstC); + }}); + } + } + rfMax = getMax(sfMax, rmsFirstA, rmsFirstB, rmsFirstC); + if (openTri) { + rfMin = getMinOpen(sfMin, rmsFirstA, rmsFirstC); + } else { + rfMin = getMin(sfMin, rmsFirstA, rmsFirstB, rmsFirstC); + } + } + RmsData rmsData1 = new RmsData(); + rmsData1.setAValue(rAValue); + rmsData1.setBValue(rBValue); + rmsData1.setCValue(rCValue); + rmsData1.setMax(rfMax); + rmsData1.setMin(rfMin); + + waveDataDetail.setInstantData(instantData); + waveDataDetail.setRmsData(rmsData1); + waveDataDetail.setIsOpen(openTri); + waveDataDetails.add(waveDataDetail); + } + /************ Modify by yexb -----end ***********/ + return waveDataDetails; + } + + private static Float getMinOpen(Float temp, float tempA, float tempB) { + temp = temp < tempA ? temp : tempA; + temp = temp < tempB ? temp : tempB; + return temp; + } + + + private static float getMin(float temp, float tempA, float tempB, float tempC) { + temp = Math.min(temp, tempA); + temp = Math.min(temp, tempB); + temp = Math.min(temp, tempC); + return temp; + } + + private static float getMax(float temp, float tempA, float tempB, float tempC) { + temp = Math.max(temp, tempA); + temp = Math.max(temp, tempB); + temp = Math.max(temp, tempC); + return temp; + } +}