From aad5943d64f588abb1257481bd3ade4bcc4f2ea3 Mon Sep 17 00:00:00 2001 From: hongawen <83944980@qq.com> Date: Fri, 17 Apr 2026 15:44:18 +0800 Subject: [PATCH] =?UTF-8?q?fix(waveform):=20=E4=BF=AE=E5=A4=8D=E5=BD=95?= =?UTF-8?q?=E6=B3=A2=E6=96=87=E4=BB=B6=E5=A4=84=E7=90=86=E4=B8=AD=E7=9A=84?= =?UTF-8?q?RMS=E6=AE=B5=E9=80=BB=E8=BE=91=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在RateDTO初始化时设置bRMSFlag默认值为false,确保16~31点/周波段按普通抽点处理 - 修复RMS段与普通抽点的控制流程分离,避免共享取模条件导致的逻辑混乱 - 优化RMS段处理逻辑,添加周波索引推进机制防止重复处理 - 修复2点/周波时半周波位置的采样点切换逻辑 - 添加段末尾对齐机制,确保外层循环能稳定跳转到下一段起点 - 更新测试文件路径配置,使用新的测试数据文件 --- .../file/component/WaveFileComponent.java | 330 +++++++++--------- 1 file changed, 168 insertions(+), 162 deletions(-) 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 index 412328635..3432b5726 100644 --- 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 @@ -515,6 +515,8 @@ public class WaveFileComponent { comtradeCfgDTO.setNAllWaveNum(comtradeCfgDTO.getNAllWaveNum() + nWaveNum); // 将最低采样率替换到本段录波内 RateDTO tmpRateDTO = new RateDTO(); + // C# 原实现中 bool 默认是 false,16~31 点/周波段也应按普通抽点处理 + tmpRateDTO.bRMSFlag = false; // 有效值标志,如果是有效值,那么就需要反向补点,而不是抽点 if (comtradeCfgDTO.getLstRate().get(iRate).getNOneSample() >= 32) { //YXB 2025-08-27 @@ -566,188 +568,192 @@ public class WaveFileComponent { } } tmpRateDTO = comtradeCfgDTO.getLstRate().get(nIndex); - //YXB 2025-08-27 如果是有效值,那么需要去补点,而不是抽点 - if (newLstRate.get(nIndex).bRMSFlag == true) { + dfValue = (float) 20 / tmpRateDTO.getNOneSample(); + // C# 原实现中 RMS 段与普通抽点是两条独立控制流,不能挂在同一个取模条件下 + if (Boolean.TRUE.equals(newLstRate.get(nIndex).bRMSFlag)) { //计算本段补点采样间隔 nWaveSpan = newLstRate.get(nIndex).getNOneSample() / tmpRateDTO.getNOneSample(); - } else { - // 计算本段抽点采样间隔 - nWaveSpan = tmpRateDTO.getNOneSample() / newLstRate.get(nIndex).getNOneSample(); + // 计算有多少个周波 + long allWaveTemp = newLstRate.get(nIndex).getNSampleNum() / newLstRate.get(nIndex).getNOneSample(); + // 本段需要补多少点 + long allempSample = newLstRate.get(nIndex).getNOneSample(); + int segmentEndIndex = (int) (nOffSet + tmpRateDTO.getNSampleNum() - 1); + for (int iWaveTemp = 0; iWaveTemp < allWaveTemp; iWaveTemp++) { + for (int mTempSample = 0; mTempSample < allempSample; mTempSample++) { + // 2 点/周波时,半周波位置需要切换到该周波的第二个原始采样点 + if (mTempSample / nWaveSpan == 1 && mTempSample % nWaveSpan == 0) { + i++; + } + //存储局部数据集合,包含了时间,A,B,C三相 + List 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, 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) 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++; + } + } + // 某些文件的段点数并不是原始每周波点数的整倍数。 + // RMS 段处理完成后,强制把原始游标对齐到当前段末尾, + // 这样外层 for 的下一次自增才能稳定落到下一段起点,避免重复进入同一 RMS 段。 + i = segmentEndIndex; + continue; } - dfValue = (float) 20 / tmpRateDTO.getNOneSample(); + // 计算本段抽点采样间隔 + nWaveSpan = tmpRateDTO.getNOneSample() / newLstRate.get(nIndex).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(); + for (int j = 0; j < comtradeCfgDTO.getNAnalogNum(); j++) { + //数据只有电压ABC三相数据,不展示U0、I0等数据 YXB2020-10-09 去除相别为N相的数据 + if (comtradeCfgDTO.getLstAnalogDTO().get(j).getSzPhasicName().equalsIgnoreCase("N")) { + break; + } - 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; - } - } - } + float fCoef = comtradeCfgDTO.getLstAnalogDTO().get(j).getFCoefficent(); + fValue = BitConverter.byte2ToUnsignedShort(datArray, i * nBlockSize + 2 * 4 + j * 2) * fCoef; - //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++; + //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; } } - } 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; + //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; } } - //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; } - //判断单位是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; - } + } 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); + //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); } } } @@ -1650,8 +1656,8 @@ public class WaveFileComponent { 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"); + InputStream cfgStream = waveFileComponent.getFileInputStreamByFilePath("C:\\Users\\Administrator\\Desktop\\wave\\PQMonitor_PQM2_006970_20260320_175033_734.CFG"); + InputStream datStream = waveFileComponent.getFileInputStreamByFilePath("C:\\Users\\Administrator\\Desktop\\wave\\PQMonitor_PQM2_006970_20260320_175033_734.DAT"); // 获取瞬时波形 //获取原始波形值 WaveDataDTO waveDataDTO = waveFileComponent.getComtrade(cfgStream, datStream, 1); d = new Date();