From 1924947f35dde9100747eed87c3538e16f0b21fa Mon Sep 17 00:00:00 2001 From: hongawen <83944980@qq.com> Date: Wed, 15 Apr 2026 11:53:44 +0800 Subject: [PATCH] =?UTF-8?q?yxb=E6=89=8D=E6=98=AF=E5=A4=A7=E5=82=BB?= =?UTF-8?q?=E9=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../temp/component/WaveFileComponent.java | 1670 +++++++++++++++++ .../temp/component/WavePicComponent.java | 303 +++ tools/wave-tool/temp/pojo/bo/InstantData.java | 25 + tools/wave-tool/temp/pojo/bo/RmsData.java | 25 + .../temp/pojo/bo/WaveDataDetail.java | 35 + tools/wave-tool/temp/pojo/dto/AnalogDTO.java | 46 + .../temp/pojo/dto/ComtradeCfgDTO.java | 54 + tools/wave-tool/temp/pojo/dto/DigitalDTO.java | 30 + .../temp/pojo/dto/EigenvalueDTO.java | 28 + .../wave-tool/temp/pojo/dto/MutationDTO.java | 27 + tools/wave-tool/temp/pojo/dto/RateDTO.java | 27 + .../wave-tool/temp/pojo/dto/WaveDataDTO.java | 46 + .../temp/pojo/enums/WaveFileResponseEnum.java | 34 + tools/wave-tool/temp/utils/WaveUtil.java | 194 ++ 14 files changed, 2544 insertions(+) create mode 100644 tools/wave-tool/temp/component/WaveFileComponent.java create mode 100644 tools/wave-tool/temp/component/WavePicComponent.java create mode 100644 tools/wave-tool/temp/pojo/bo/InstantData.java create mode 100644 tools/wave-tool/temp/pojo/bo/RmsData.java create mode 100644 tools/wave-tool/temp/pojo/bo/WaveDataDetail.java create mode 100644 tools/wave-tool/temp/pojo/dto/AnalogDTO.java create mode 100644 tools/wave-tool/temp/pojo/dto/ComtradeCfgDTO.java create mode 100644 tools/wave-tool/temp/pojo/dto/DigitalDTO.java create mode 100644 tools/wave-tool/temp/pojo/dto/EigenvalueDTO.java create mode 100644 tools/wave-tool/temp/pojo/dto/MutationDTO.java create mode 100644 tools/wave-tool/temp/pojo/dto/RateDTO.java create mode 100644 tools/wave-tool/temp/pojo/dto/WaveDataDTO.java create mode 100644 tools/wave-tool/temp/pojo/enums/WaveFileResponseEnum.java create mode 100644 tools/wave-tool/temp/utils/WaveUtil.java diff --git a/tools/wave-tool/temp/component/WaveFileComponent.java b/tools/wave-tool/temp/component/WaveFileComponent.java new file mode 100644 index 0000000..4123286 --- /dev/null +++ b/tools/wave-tool/temp/component/WaveFileComponent.java @@ -0,0 +1,1670 @@ +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.util.ArrayUtil; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.StrUtil; +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())) { + throw new BusinessException(WaveFileResponseEnum.CFG_DATA_ERROR); + } + + /*****根据通道号计算相别** 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()); + + // 组装解析抬头 + getWaveTitle(waveDataDTO, comtradeCfgDTO); + + // 解析.dat文件 + List> listWaveData = getComtradeDat(comtradeCfgDTO, datStream, iType); + + waveDataDTO.setComtradeCfgDTO(comtradeCfgDTO); + + waveDataDTO.setListWaveData(listWaveData); + + //add by hongawen,将暂态触发起始时间记录下来 + waveDataDTO.setTime(DateUtil.format(comtradeCfgDTO.getTimeTrige(), DatePattern.NORM_DATETIME_MS_PATTERN)); + /*****根据通道号计算相别** 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(); + //获取最终采样率 + int 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(); + try (InputStreamReader read = new InputStreamReader(cfgStream, CharsetUtil.CHARSET_GBK); BufferedReader bufferedReader = new BufferedReader(read);) { + // 第一行不关心仅仅是一些描述类的信息 + String strFileLine = bufferedReader.readLine(); + + // 第二行需要关心第二个(模拟量的个数)和第三个参数(开关量的个数) + strFileLine = bufferedReader.readLine(); + // 按“,”进行分割 + String[] strTempArray = strFileLine.split(StrUtil.COMMA); + // 总个数 + comtradeCfgDTO.setNChannelNum(Integer.parseInt(strTempArray[0])); + // 模拟量的个数 + comtradeCfgDTO.setNAnalogNum(Integer.parseInt(strTempArray[1].substring(0, strTempArray[1].length() - 1))); + // 开关量的个数 + comtradeCfgDTO.setNDigitalNum(Integer.parseInt(strTempArray[2].substring(0, strTempArray[2].length() - 1))); + + // 从第三行开始的ComtradeCfg.nChannelNum行是模拟量通道和数字量通道 + 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); + //通道序号 + analogDTO.setNIndex(Integer.parseInt(strTempArray[0])); + // 通道名称 + analogDTO.setSzChannleName(strTempArray[1]); + // 相位名称 + analogDTO.setSzPhasicName(strTempArray[2]); + // 监视的通道名称 + analogDTO.setSzMonitoredChannleName(strTempArray[3]); + // 通道的单位 + analogDTO.setSzUnitName(strTempArray[4]); + // 通道的系数 + analogDTO.setFCoefficent(Float.parseFloat(strTempArray[5])); + // 通道的偏移量 + analogDTO.setFOffset(Float.parseFloat(strTempArray[6])); + // 起始采样时间的偏移量 + analogDTO.setFTimeOffset(Float.parseFloat(strTempArray[7])); + // 采样值的最小值 + analogDTO.setNMin(Integer.parseInt(strTempArray[8])); + // 采样值的最大值 + analogDTO.setNMax(Integer.parseInt(strTempArray[9])); + // 一次变比 + analogDTO.setFPrimary(Float.parseFloat(strTempArray[10])); + // 二次变比 + analogDTO.setFSecondary(Float.parseFloat(strTempArray[11])); + // 一次值还是二次值标志 + analogDTO.setSzValueType(strTempArray[12]); + } + + //WW 2019-11-14 // 采样频率 + String freqLine = bufferedReader.readLine(); + int nFreq; + try { + // 先尝试解析为double再四舍五入为整数,以兼容"50.00"这样的格式 + nFreq = (int) Math.round(Double.parseDouble(freqLine)); + } catch (NumberFormatException e) { + // 如果失败则使用原来的整数解析方式 + nFreq = Integer.parseInt(freqLine); + } + + // 获取采样段数 + strFileLine = bufferedReader.readLine(); + int nRates = Integer.parseInt(strFileLine); + comtradeCfgDTO.setNRates(nRates); + // 获得每段的采样率 //采样率 + List lstRate = new ArrayList<>(); + int 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 + double doubleValue = Double.parseDouble(strTempArray[0]); // 解析为 double + int result = (int) (doubleValue / nFreq); // 强制转换为 int + rateDTO.setNOneSample(result); + // 总点数 //这里的strTemp是一个偏移量 + rateDTO.setNSampleNum((Integer.parseInt(strTempArray[1]) - nOffset)); + nOffset += rateDTO.getNSampleNum(); + lstRate.add(rateDTO); + } + comtradeCfgDTO.setLstRate(lstRate); + // 增加读取波形起始时间个结束时间 + String timeFormat = "dd/MM/yyyy,HH:mm:ss.SSS"; + // 波形起始时间 + strFileLine = bufferedReader.readLine(); + strFileLine = strFileLine.substring(0, strFileLine.length() - 3); + comtradeCfgDTO.setTimeStart(DateUtil.parse(strFileLine, timeFormat)); + + // 暂态触发时间 + strFileLine = bufferedReader.readLine(); + strFileLine = strFileLine.substring(0, strFileLine.length() - 3); + comtradeCfgDTO.setTimeTrige(DateUtil.parse(strFileLine, timeFormat)); + + // 获取触发时间的时间 + 毫秒 + Calendar calendar = DateUtil.calendar(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; + } + return comtradeCfgDTO; + } + + /********************************* + * 读取dat方法 + * param strFilePath .dat访问路径 + * param strFilePath .dat访问路径 + * param iType 访问波形类型 + * List> 返回波形瞬时值 + **********************************/ + private List> getComtradeDat(ComtradeCfgDTO comtradeCfgDTO, InputStream datStream, int iType) { + //返回数据,如果仅仅做展示后期考虑换String类型,降低内存开销 + List> listWaveData = new ArrayList<>(); + //初始化xValue的值 + float xValueAll = 0; + //判断是否首次登陆 + boolean blxValue = false; + byte[] datArray; + try { + datArray = IoUtil.readBytes(datStream); + if (ArrayUtil.isEmpty(datArray)) { + throw new BusinessException(WaveFileResponseEnum.DAT_DATA_ERROR); + } + // 计算每个单独的数据块的大小 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 = (int)Math.floor(datArray.length / nBlockSize); + + // 获取采样率 + int finalSampleRate = getFinalWaveSample(comtradeCfgDTO.getLstRate(), iType); + if (finalSampleRate != -1) { + //设置最终采样率 + comtradeCfgDTO.setFinalSampleRate(finalSampleRate); + // 计算转换后的采样率 + int nnInd = 0; + // 抽点后总共多少点数据 + int nWaveNum; + //抽点后新的的采样率 + List newLstRate = new ArrayList<>(); + for (int iRate = 0; iRate < comtradeCfgDTO.getNRates(); iRate++) { + // 计算本段录波总共有多少波形 + nWaveNum = comtradeCfgDTO.getLstRate().get(iRate).getNSampleNum() / comtradeCfgDTO.getLstRate().get(iRate).getNOneSample(); + //设置总波形大小 + comtradeCfgDTO.setNAllWaveNum(comtradeCfgDTO.getNAllWaveNum() + nWaveNum); + // 将最低采样率替换到本段录波内 + RateDTO tmpRateDTO = new RateDTO(); + // 有效值标志,如果是有效值,那么就需要反向补点,而不是抽点 + if (comtradeCfgDTO.getLstRate().get(iRate).getNOneSample() >= 32) { + //YXB 2025-08-27 + tmpRateDTO.bRMSFlag = false; + } + //如果采样是全波有效值或者半波有效值,需要去补足周波点数 YXB 2025-08-27 + else if (comtradeCfgDTO.getLstRate().get(iRate).getNOneSample() <= 2) { + //YXB 2025-08-27 + tmpRateDTO.bRMSFlag = true; + } + 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); + } + + 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); + // 判断是否进入下一段 + if (i == tmpRateDTO.getNSampleNum() + nOffSet) { + nOffSet += tmpRateDTO.getNSampleNum(); + nIndex++; + if (nIndex == nnInd) { + break; + } + } + tmpRateDTO = comtradeCfgDTO.getLstRate().get(nIndex); + //YXB 2025-08-27 如果是有效值,那么需要去补点,而不是抽点 + if (newLstRate.get(nIndex).bRMSFlag == true) { + //计算本段补点采样间隔 + nWaveSpan = newLstRate.get(nIndex).getNOneSample() / tmpRateDTO.getNOneSample(); + } else { + // 计算本段抽点采样间隔 + nWaveSpan = tmpRateDTO.getNOneSample() / newLstRate.get(nIndex).getNOneSample(); + } + + dfValue = (float) 20 / tmpRateDTO.getNOneSample(); + // 判断是否到了需要抽的采样点 + if (i % nWaveSpan == 0) { + // 计算每个通道的值 + //存储局部数据集合,包含了时间,A,B,C三相 + List tmpWaveData = new ArrayList<>(); + //YXB 2025-08-27 如果是有效值,那么需要去补点,而不是抽点 + if (newLstRate.get(nIndex).bRMSFlag == true) { + // 计算有多少个周波 + long allWaveTemp = newLstRate.get(nIndex).getNSampleNum() / newLstRate.get(nIndex).getNOneSample(); + // 本段需要补多少点 + long allempSample = newLstRate.get(nIndex).getNOneSample(); + + int currentDataIndex = i; + for (int iWaveTemp = 0; iWaveTemp < allWaveTemp; iWaveTemp++) { + for (int mTempSample = 0; mTempSample < allempSample; mTempSample++) { + tmpWaveData = new ArrayList<>(); + for (int j = 0; j < comtradeCfgDTO.getNAnalogNum(); j++) { + if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzPhasicName().equalsIgnoreCase("N")) { + break; + } + float fCoef = comtradeCfgDTO.getLstAnalogDTO().get(j).getFCoefficent(); + fValue = BitConverter.byte2ToUnsignedShort(datArray, currentDataIndex * nBlockSize + 2 * 4 + j * 2) * fCoef; + //WW 2019-11-14 + /************************* + * 1、接口返回的默认是二次值 + * 2、P是一次值 S是二次值 + * 3、S(二次值)情况下: + * ①、单位为"V"时候则直接等于; + * ②、单位为"kV"时候需要乘以1000 + * 4、P(一次值)情况下: + * ①、单位为"V"时候则直接等于; + * ②、单位为"kV"时候需要乘以1000 + *************************/ + //P是一次值 S是二次值 + if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzValueType().equalsIgnoreCase("S")) { + //判断单位是V还是kV + if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("KV")) { + fValue = fValue * 1000.0f; + } else { + fValue = fValue; + } + } + //P是一次值 S是二次值 + else if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzValueType().equalsIgnoreCase("P")) { + //判断单位是V还是kV + if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("V")) { + //根据cfg内的变比,将一次值转换成二次值 + if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) { + fValue = fValue * comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary(); + } else { + fValue = fValue; + } + } + //判断单位是V还是kV + else if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("KV")) { + //根据cfg内的变比,将一次值转换成二次值 + if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) { + fValue = fValue * 1000.0f * comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary(); + } else { + fValue = fValue; + } + } else //还有可能是 电流,单位是A + { + //根据cfg内的变比,将一次值转换成二次值 + if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) { + fValue = fValue * comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary(); + } else { + fValue = fValue; + } + } + } + + //xValue前移量,假如是第一次时候则需要前移 + if (!blxValue && j == 0) { + xValueAll = (float) (currentDataIndex * 20) / tmpRateDTO.getNOneSample() - comtradeCfgDTO.getNPush(); + blxValue = true; + //只增加一个xValue的值 //增加时间值 + tmpWaveData.add((float) (Math.round(xValueAll * 100)) / 100); + } else if (j == 0) { + xValueAll += (float) dfValue / nWaveSpan; + //只增加一个xValue的值 //增加时间值 + tmpWaveData.add((float) (Math.round(xValueAll * 100)) / 100); + } + + //不同通道yValue的值都需要增加,最终成ABC三相 //每个通道的值 + tmpWaveData.add((float) (Math.round(fValue * 100)) / 100); + } + //把每个单独的值赋予到整体里面去 + listWaveData.add(tmpWaveData); + } + // 把每个单独的值赋予到整体里面去 + if (iWaveTemp < (allWaveTemp - 1)) { + currentDataIndex++; + } + } + } else { + for (int j = 0; j < comtradeCfgDTO.getNAnalogNum(); j++) { + //数据只有电压ABC三相数据,不展示U0、I0等数据 YXB2020-10-09 去除相别为N相的数据 + if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzPhasicName().equalsIgnoreCase("N")) { + break; + } + + float fCoef = comtradeCfgDTO.getLstAnalogDTO().get(j).getFCoefficent(); + fValue = BitConverter.byte2ToUnsignedShort(datArray, i * nBlockSize + 2 * 4 + j * 2) * fCoef; + + //WW 2019-11-14 + /************************** + * 1、接口返回的默认是二次值 + * 2、P是一次值 S是二次值 + * 3、S(二次值)情况下: + * ①、单位为"V"时候则直接等于; + * ②、单位为"kV"时候需要乘以1000 + * 4、P(一次值)情况下: + * ①、单位为"V"时候则直接等于; + * ②、单位为"kV"时候需要乘以1000 + **************************/ + //P是一次值 S是二次值 + if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzValueType().equalsIgnoreCase("S")) { + //判断单位是V还是kV + if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("KV")) { + fValue = fValue * 1000.0f; + } else { + fValue = fValue; + } + } + //P是一次值 S是二次值 + else if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzValueType().equalsIgnoreCase("P")) { + //判断单位是V还是kV + if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("V")) { + //根据cfg内的变比,将一次值转换成二次值 + if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) { + fValue = fValue * comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary(); + } else { + fValue = fValue; + } + } + //判断单位是V还是kV + else if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("KV")) { + //根据cfg内的变比,将一次值转换成二次值 + if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) { + fValue = fValue * 1000.0f * comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary(); + } else { + fValue = fValue; + } + } else //还有可能是 电流,单位是A + { + //根据cfg内的变比,将一次值转换成二次值 + if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) { + fValue = fValue * comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary(); + } else { + fValue = fValue; + } + } + } + //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) { + e.printStackTrace(); + throw new BusinessException(WaveFileResponseEnum.DAT_DATA_ERROR); + } + + return listWaveData; + } + +// private List> getComtradeDat(ComtradeCfgDTO comtradeCfgDTO, InputStream datStream, int iType) { +// //返回数据,如果仅仅做展示后期考虑换String类型,降低内存开销 +// List> listWaveData = new ArrayList<>(); +// //初始化xValue的值 +// float xValueAll = 0; +// //判断是否首次登陆 +// boolean blxValue = false; +// byte[] datArray; +// try { +// datArray = IoUtil.readBytes(datStream); +// if (ArrayUtil.isEmpty(datArray)) { +// throw new BusinessException(WaveFileResponseEnum.DAT_DATA_ERROR); +// } +// // 计算每个单独的数据块的大小 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 = (int)Math.floor(datArray.length / nBlockSize); +// +// // 获取采样率 +// int finalSampleRate = getFinalWaveSample(comtradeCfgDTO.getLstRate(), iType); +// if (finalSampleRate != -1) { +// //设置最终采样率 +// comtradeCfgDTO.setFinalSampleRate(finalSampleRate); +// // 计算转换后的采样率 +// int nnInd = 0; +// // 抽点后总共多少点数据 +// int 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(); +// // 有效值标志,如果是有效值,那么就需要反向补点,而不是抽点 +// if (comtradeCfgDTO.getLstRate().get(iRate).getNOneSample() >= 32) { +// //YXB 2025-08-27 +// tmpRateDTO.bRMSFlag = false; +// } +// //如果采样是全波有效值或者半波有效值,需要去补足周波点数 YXB 2025-08-27 +// else if (comtradeCfgDTO.getLstRate().get(iRate).getNOneSample() <= 2) { +// //YXB 2025-08-27 +// tmpRateDTO.bRMSFlag = true; +// } +// 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); +// // 判断是否进入下一段 +// if (i == tmpRateDTO.getNSampleNum() + nOffSet) { +// nOffSet += tmpRateDTO.getNSampleNum(); +// nIndex++; +// if (nIndex == nnInd) { +// break; +// } +// } +// tmpRateDTO = comtradeCfgDTO.getLstRate().get(nIndex); +// //YXB 2025-08-27 如果是有效值,那么需要去补点,而不是抽点 +// if (newLstRate.get(nIndex).bRMSFlag == true) { +// //计算本段补点采样间隔 +// nWaveSpan = newLstRate.get(nIndex).getNOneSample() / tmpRateDTO.getNOneSample(); +// } else { +// // 计算本段抽点采样间隔 +// nWaveSpan = tmpRateDTO.getNOneSample() / newLstRate.get(nIndex).getNOneSample(); +// } +// +// dfValue = (float) 20 / tmpRateDTO.getNOneSample(); +// // 判断是否到了需要抽的采样点 +// if (i % nWaveSpan == 0) { +// // 计算每个通道的值 +// //存储局部数据集合,包含了时间,A,B,C三相 +// List tmpWaveData = new ArrayList<>(); +// //YXB 2025-08-27 如果是有效值,那么需要去补点,而不是抽点 +// if (newLstRate.get(nIndex).bRMSFlag == true) { +// // 计算有多少个周波 +// long allWaveTemp = newLstRate.get(nIndex).getNSampleNum() / newLstRate.get(nIndex).getNOneSample(); +// // 本段需要补多少点 +// long allempSample = newLstRate.get(nIndex).getNOneSample(); +// //int iStartWaveTemp = i ;// 开始补点的起点 +// for (int iWaveTemp = 0; iWaveTemp < allWaveTemp; iWaveTemp++) { +// for (int mTempSample = 0; mTempSample < allempSample; mTempSample++) { +// //最多只有半波有效值,也就是每周波是1个或者2个点,然后去补最少16个点 +// if (mTempSample / nWaveSpan == 1 && mTempSample % nWaveSpan == 0) { +// i++; +// } +// //存储局部数据集合,包含了时间,A,B,C三相 +// tmpWaveData = new ArrayList<>(); +// for (int j = 0; j < comtradeCfgDTO.getNAnalogNum(); j++) { +// //数据只有电压ABC三相数据,不展示U0、I0等数据 YXB2020-10-09 去除相别为N相的数据 +// if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzPhasicName().equalsIgnoreCase("N")) { +// break; +// } +// float fCoef = comtradeCfgDTO.getLstAnalogDTO().get(j).getFCoefficent(); +// +// if((i * nBlockSize + 2 * 4 + j * 2) == 2437568){ +// System.out.println(55); +// } +// fValue = BitConverter.byte2ToUnsignedShort(datArray, i * nBlockSize + 2 * 4 + j * 2) * fCoef; +// //WW 2019-11-14 +// /************************* +// * 1、接口返回的默认是二次值 +// * 2、P是一次值 S是二次值 +// * 3、S(二次值)情况下: +// * ①、单位为"V"时候则直接等于; +// * ②、单位为"kV"时候需要乘以1000 +// * 4、P(一次值)情况下: +// * ①、单位为"V"时候则直接等于; +// * ②、单位为"kV"时候需要乘以1000 +// *************************/ +// //P是一次值 S是二次值 +// if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzValueType().equalsIgnoreCase("S")) { +// //判断单位是V还是kV +// if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("KV")) { +// fValue = fValue * 1000.0f; +// } else { +// fValue = fValue; +// } +// } +// //P是一次值 S是二次值 +// else if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzValueType().equalsIgnoreCase("P")) { +// //判断单位是V还是kV +// if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("V")) { +// //根据cfg内的变比,将一次值转换成二次值 +// if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) { +// fValue = fValue * comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary(); +// } else { +// fValue = fValue; +// } +// } +// //判断单位是V还是kV +// else if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("KV")) { +// //根据cfg内的变比,将一次值转换成二次值 +// if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) { +// fValue = fValue * 1000.0f * comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary(); +// } else { +// fValue = fValue; +// } +// } else //还有可能是 电流,单位是A +// { +// //根据cfg内的变比,将一次值转换成二次值 +// if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) { +// fValue = comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary(); +// } else { +// fValue = fValue; +// } +// } +// } +// +// //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) dfValue / nWaveSpan; +// //只增加一个xValue的值 //增加时间值 +// tmpWaveData.add((float) (Math.round(xValueAll * 100)) / 100); +// } +// +// //不同通道yValue的值都需要增加,最终成ABC三相 //每个通道的值 +// tmpWaveData.add((float) (Math.round(fValue * 100)) / 100); +// } +// //把每个单独的值赋予到整体里面去 +// listWaveData.add(tmpWaveData); +// } +// // 把每个单独的值赋予到整体里面去 +// if (iWaveTemp < (allWaveTemp - 1)) { +// i++; +// } +// } +// } else { +// for (int j = 0; j < comtradeCfgDTO.getNAnalogNum(); j++) { +// //数据只有电压ABC三相数据,不展示U0、I0等数据 YXB2020-10-09 去除相别为N相的数据 +// if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzPhasicName().equalsIgnoreCase("N")) { +// break; +// } +// +// float fCoef = comtradeCfgDTO.getLstAnalogDTO().get(j).getFCoefficent(); +// fValue = BitConverter.byte2ToUnsignedShort(datArray, i * nBlockSize + 2 * 4 + j * 2) * fCoef; +// +// //WW 2019-11-14 +// /************************** +// * 1、接口返回的默认是二次值 +// * 2、P是一次值 S是二次值 +// * 3、S(二次值)情况下: +// * ①、单位为"V"时候则直接等于; +// * ②、单位为"kV"时候需要乘以1000 +// * 4、P(一次值)情况下: +// * ①、单位为"V"时候则直接等于; +// * ②、单位为"kV"时候需要乘以1000 +// **************************/ +// //P是一次值 S是二次值 +// if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzValueType().equalsIgnoreCase("S")) { +// //判断单位是V还是kV +// if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("KV")) { +// fValue = fValue * 1000.0f; +// } else { +// fValue = fValue; +// } +// } +// //P是一次值 S是二次值 +// else if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzValueType().equalsIgnoreCase("P")) { +// //判断单位是V还是kV +// if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("V")) { +// //根据cfg内的变比,将一次值转换成二次值 +// if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) { +// fValue = fValue * comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary(); +// } else { +// fValue = fValue; +// } +// } +// //判断单位是V还是kV +// else if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzUnitName().equalsIgnoreCase("KV")) { +// //根据cfg内的变比,将一次值转换成二次值 +// if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) { +// fValue = fValue * 1000.0f * comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary(); +// } else { +// fValue = fValue; +// } +// } else //还有可能是 电流,单位是A +// { +// //根据cfg内的变比,将一次值转换成二次值 +// if (comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary() != 0.0f) { +// fValue = comtradeCfgDTO.getLstAnalogDTO().get(j).getFSecondary() / comtradeCfgDTO.getLstAnalogDTO().get(j).getFPrimary(); +// } else { +// fValue = fValue; +// } +// } +// } +// //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) { +// e.printStackTrace(); +// throw new BusinessException(WaveFileResponseEnum.DAT_DATA_ERROR); +// } +// +// return listWaveData; +// } + + + /********************************* + * 获取最小(最终)采样率方法 + * @param lstRate cfg中关于采样率参数 + * @return 返回最小采样率 + **********************************/ + private int getFinalWaveSample(List lstRate, int iType) { + // 最终返回采样率 + int nFinalOneSample = -1; + // 最小采样率 + int nMinOneSample = -1; + if (!lstRate.isEmpty()) { + nMinOneSample = lstRate.get(0).getNOneSample(); + int tmpOneSample; + for (RateDTO rateDTO : lstRate) { + tmpOneSample = rateDTO.getNOneSample(); + //YXB 2025-08-27 32->16 + if (tmpOneSample >= 16) { + 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; + } else { + nFinalOneSample = nMinOneSample; + } + 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 void getWaveTitle(WaveDataDTO waveDataDTO, ComtradeCfgDTO comtradeCfgDTO) { + //编辑数据标题 YXB2020-10-09 去除相别为N相的数据//存储数据标题 + List tmpWaveTitle = new ArrayList<>(); + List channelName = new ArrayList<>(); + // 模拟量通道记录类 + AnalogDTO analogDTO; + tmpWaveTitle.add("Time"); + channelName.add("/"); + 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() + "相"); + channelName.add(analogDTO.getSzChannleName()); + } + } + waveDataDTO.setWaveTitle(tmpWaveTitle); + waveDataDTO.setChannelNames(channelName); + } + + /********************************* + * 由.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("F:\\PQ_PQLD3_9_20250821_081038_640.cfg"); + InputStream datStream = waveFileComponent.getFileInputStreamByFilePath("F:\\PQ_PQLD3_9_20250821_081038_640.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); + System.out.println(1); + } + +} diff --git a/tools/wave-tool/temp/component/WavePicComponent.java b/tools/wave-tool/temp/component/WavePicComponent.java new file mode 100644 index 0000000..9606748 --- /dev/null +++ b/tools/wave-tool/temp/component/WavePicComponent.java @@ -0,0 +1,303 @@ +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.pojo.constant.PicCommonData; +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.NoArgsConstructor; +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.*; +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 generateInstantImageZl(List waveDataDetails) { + String firstPic = null, secondPic = null, thirdPic = null, forthPic = null; + for (WaveDataDetail waveDataDetail : waveDataDetails) { + if (waveDataDetail.getChannelName().toUpperCase().startsWith("SU")) { + firstPic = 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() + ); + } else if (waveDataDetail.getChannelName().toUpperCase().startsWith("SI")) { + thirdPic = 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() + ); + } else if (waveDataDetail.getChannelName().toUpperCase().startsWith("LU")) { + 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() + ); + } else { + forthPic = 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() + ); + } + } + return composeImageZl(firstPic, secondPic, thirdPic, forthPic); + } + + /*** + * 绘制RMS波形图治理 + * @author hongawen + * @date 2023/9/21 15:32 + * @return String 文件地址 + */ + public String generateRmsImageZl(List waveDataDetails) { + String firstPic = null, secondPic = null, thirdPic = null, forthPic = null; + for (WaveDataDetail waveDataDetail : waveDataDetails) { + if (waveDataDetail.getChannelName().toUpperCase().startsWith("SU")) { + firstPic = 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() + ); + } else if (waveDataDetail.getChannelName().toUpperCase().startsWith("SI")) { + thirdPic = 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() + ); + } else if (waveDataDetail.getChannelName().toUpperCase().startsWith("LU")) { + 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() + ); + } else { + forthPic = 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() + ); + } + } + return composeImageZl(firstPic, secondPic, thirdPic, forthPic); + } + + /*** + * 合并4个原图 + * @author hongawen + * @date 2023/9/28 14:45 + * @return String + */ + private String composeImageZl(String firstPic, String secondPic, String thirdPic, String forthPic) { + 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[] ImageArrayTwo = new int[width * height]; + ImageArrayTwo = imageTwo.getRGB(0, 0, width, height, ImageArrayTwo, 0, width); + //第三张图片 base64截取删除前缀data:image/png;base64, + BufferedImage imageThree = ImgUtil.toBufferedImage(ImgUtil.toImage(thirdPic.substring(22)), ImgUtil.IMAGE_TYPE_PNG); + int[] ImageArrayThree = new int[width * height]; + ImageArrayThree = imageThree.getRGB(0, 0, width, height, ImageArrayThree, 0, width); + //第四张图片 base64截取删除前缀data:image/png;base64, + BufferedImage imageForth = ImgUtil.toBufferedImage(ImgUtil.toImage(forthPic.substring(22)), ImgUtil.IMAGE_TYPE_PNG); + int[] ImageArrayForth = new int[width * height]; + ImageArrayForth = imageForth.getRGB(0, 0, width, height, ImageArrayForth, 0, width); + //新图片 + BufferedImage imageNew = new BufferedImage(width, height * 4, BufferedImage.TYPE_INT_RGB); + BufferedImageGraphicsConfig config = BufferedImageGraphicsConfig.getConfig(imageNew); + imageNew = config.createCompatibleImage(width, height * 4, Transparency.TRANSLUCENT); + imageNew.setRGB(0, 0, width, height, imageArrayOne, 0, width); + imageNew.setRGB(0, height, width, height, ImageArrayTwo, 0, width); + imageNew.setRGB(0, height * 2, width, height, ImageArrayThree, 0, width); + imageNew.setRGB(0, height * 3, width, height, ImageArrayForth, 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); + } + } + + + /*** + * 绘制瞬时波形图 + * @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 + if (firstPic.contains(PicCommonData.PNG_PREFIX)) { + firstPic = firstPic.replace(PicCommonData.PNG_PREFIX, ""); + } + byte[] bytes = Base64.getDecoder().decode(firstPic); + picPath = fileStorageUtil.uploadStream(new ByteArrayInputStream(bytes), 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 + if (firstPic.contains(PicCommonData.PNG_PREFIX)) { + firstPic = firstPic.replace(PicCommonData.PNG_PREFIX, ""); + } + byte[] bytes = Base64.getDecoder().decode(firstPic); + picPath = fileStorageUtil.uploadStream(new ByteArrayInputStream(bytes), 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); + } + } + + /** + * app越限指标图 + * @param title + * @param values + * @param limitName + * @param limit + * @return + */ + public String generateSteadyTargetImage(String title, Map>> values, String limitName, List> limit) { + String firstPic = drawPicUtil.drawSteadyTargetPic(title,values,limitName,limit); + if (firstPic.contains(PicCommonData.PNG_PREFIX)) { + firstPic = firstPic.replace(PicCommonData.PNG_PREFIX, ""); + } + byte[] bytes = Base64.getDecoder().decode(firstPic); + return fileStorageUtil.uploadStream(new ByteArrayInputStream(bytes), OssPath.EVENT_WAVE_PIC, FileUtil.generateFileName("png")); + } +} diff --git a/tools/wave-tool/temp/pojo/bo/InstantData.java b/tools/wave-tool/temp/pojo/bo/InstantData.java new file mode 100644 index 0000000..b7b4775 --- /dev/null +++ b/tools/wave-tool/temp/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/tools/wave-tool/temp/pojo/bo/RmsData.java b/tools/wave-tool/temp/pojo/bo/RmsData.java new file mode 100644 index 0000000..4441181 --- /dev/null +++ b/tools/wave-tool/temp/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/tools/wave-tool/temp/pojo/bo/WaveDataDetail.java b/tools/wave-tool/temp/pojo/bo/WaveDataDetail.java new file mode 100644 index 0000000..6268c8b --- /dev/null +++ b/tools/wave-tool/temp/pojo/bo/WaveDataDetail.java @@ -0,0 +1,35 @@ +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 channelName; + + private String unit; + + private Boolean isOpen = false; + + private String title; + + private List colors= new ArrayList<>(); +} diff --git a/tools/wave-tool/temp/pojo/dto/AnalogDTO.java b/tools/wave-tool/temp/pojo/dto/AnalogDTO.java new file mode 100644 index 0000000..127b83c --- /dev/null +++ b/tools/wave-tool/temp/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/tools/wave-tool/temp/pojo/dto/ComtradeCfgDTO.java b/tools/wave-tool/temp/pojo/dto/ComtradeCfgDTO.java new file mode 100644 index 0000000..8174644 --- /dev/null +++ b/tools/wave-tool/temp/pojo/dto/ComtradeCfgDTO.java @@ -0,0 +1,54 @@ +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 Integer finalSampleRate; + // 整个波形大小 + private Integer nAllWaveNum = 0; + + /*** + * 赋值编码格式(二进制) + */ + private String strBinType; + + public static void main(String[] args) { + System.out.println(0/16); + } +} diff --git a/tools/wave-tool/temp/pojo/dto/DigitalDTO.java b/tools/wave-tool/temp/pojo/dto/DigitalDTO.java new file mode 100644 index 0000000..ab0350a --- /dev/null +++ b/tools/wave-tool/temp/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/tools/wave-tool/temp/pojo/dto/EigenvalueDTO.java b/tools/wave-tool/temp/pojo/dto/EigenvalueDTO.java new file mode 100644 index 0000000..f082491 --- /dev/null +++ b/tools/wave-tool/temp/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/tools/wave-tool/temp/pojo/dto/MutationDTO.java b/tools/wave-tool/temp/pojo/dto/MutationDTO.java new file mode 100644 index 0000000..9ef8ae9 --- /dev/null +++ b/tools/wave-tool/temp/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/tools/wave-tool/temp/pojo/dto/RateDTO.java b/tools/wave-tool/temp/pojo/dto/RateDTO.java new file mode 100644 index 0000000..8072e24 --- /dev/null +++ b/tools/wave-tool/temp/pojo/dto/RateDTO.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; + +/** + * @author yxb + * @version 1.0.0 + * @date 2022年06月02日 20:03 + * 采样率类 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RateDTO implements Serializable { + + // 1秒钟内的采样点数 + private Integer nOneSample; + // 总采样点数 + private Integer nSampleNum; + + //有效值标志,如果是有效值,那么就需要反向补点,而不是抽点 + public Boolean bRMSFlag;//YXB 2025-08-27 +} diff --git a/tools/wave-tool/temp/pojo/dto/WaveDataDTO.java b/tools/wave-tool/temp/pojo/dto/WaveDataDTO.java new file mode 100644 index 0000000..08c91a9 --- /dev/null +++ b/tools/wave-tool/temp/pojo/dto/WaveDataDTO.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; +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 channelNames; + //波形对应的值 + 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/tools/wave-tool/temp/pojo/enums/WaveFileResponseEnum.java b/tools/wave-tool/temp/pojo/enums/WaveFileResponseEnum.java new file mode 100644 index 0000000..373849a --- /dev/null +++ b/tools/wave-tool/temp/pojo/enums/WaveFileResponseEnum.java @@ -0,0 +1,34 @@ +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","波形文件数据缺失"), + CFG_DATA_ERROR("A00653","CFG文件解析有误"), + 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/tools/wave-tool/temp/utils/WaveUtil.java b/tools/wave-tool/temp/utils/WaveUtil.java new file mode 100644 index 0000000..218418d --- /dev/null +++ b/tools/wave-tool/temp/utils/WaveUtil.java @@ -0,0 +1,194 @@ +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(); + //通道名称,针对治理项目波形文件处理 + List channelNames = waveDataDTO.getChannelNames(); + 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"); + waveDataDetail.setChannelName(channelNames.get(i + 1)); + 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"); + waveDataDetail.setChannelName(channelNames.get(i * 2 + 1)); + 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"); + waveDataDetail.setChannelName(channelNames.get(i * 3 + 1)); + 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; + } +}