增加日志输出,以便观察实际波形信息

This commit is contained in:
2025-10-20 09:01:37 +08:00
parent 0a85b433ba
commit 80a886a5eb
2 changed files with 132 additions and 67 deletions

View File

@@ -876,51 +876,37 @@ public class ComtradeReader {
// 记录段的起始位置
dataBuf.getSegmentStartIndices()[seg] = sampleIndex;
// 只对超过512的段降采样到256
float targetRate = segmentSamplesPerCycle;
int downsampleMod = 1;
// 记录段的原始采样率(不做降采样)
dataBuf.getSegmentSampleRates()[seg] = segmentSamplesPerCycle;
if (segmentSamplesPerCycle > 512) {
targetRate = 256;
downsampleMod = Math.round(segmentSamplesPerCycle / 256);
log.info("段{} - 原始: {}点/周波 > 512, 降采样到256, 模数: {}",
seg, segmentSamplesPerCycle, downsampleMod);
} else {
log.info("段{} - 原始: {}点/周波, 保持不变",
seg, segmentSamplesPerCycle);
}
log.info("段{} - 原始: {}点/周波, 保留原始数据",
seg, segmentSamplesPerCycle);
// 记录段的采样率(降采样后的
dataBuf.getSegmentSampleRates()[seg] = targetRate;
// 读取当前段的数据
// 读取当前段的所有数据(不降采样)
for (int i = 0; i < segmentSamples; i++) {
int bytesRead = dis.read(buffer, 0, recordSize);
if (bytesRead != recordSize) {
break;
}
// 降采样(仅当>512时
if (i % downsampleMod == 0) {
ByteBuffer bb = ByteBuffer.wrap(buffer);
bb.order(ByteOrder.LITTLE_ENDIAN);
ByteBuffer bb = ByteBuffer.wrap(buffer);
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.getInt(); // 序号
bb.getInt(); // 时间戳
bb.getInt(); // 序号
bb.getInt(); // 时间戳
// 读取模拟通道数据
for (int ch = 0; ch < cfgInfo.getAnalogChannels() && ch < MAX_CH_NUM; ch++) {
short rawValue = bb.getShort();
dataBuf.getSmpData()[ch][sampleIndex] = rawValue;
}
sampleIndex++;
// 读取模拟通道数据
for (int ch = 0; ch < cfgInfo.getAnalogChannels() && ch < MAX_CH_NUM; ch++) {
short rawValue = bb.getShort();
dataBuf.getSmpData()[ch][sampleIndex] = rawValue;
}
sampleIndex++;
}
log.info("段{} 完成 - 起始索引: {}, 输出采样点: {}, 采样率: {}点/周波",
seg, dataBuf.getSegmentStartIndices()[seg],
sampleIndex - dataBuf.getSegmentStartIndices()[seg],
targetRate);
segmentSamplesPerCycle);
}
log.info("=== 多段数据处理完成 - 总采样点: {} ===", sampleIndex);
@@ -931,15 +917,11 @@ public class ComtradeReader {
dataBuf.getSegmentStartIndices()[0] = 0;
float samplesPerCycle = (float) cfgInfo.getSampleRate() / lineFreq;
float targetRate = samplesPerCycle;
int downsampleMod = 1;
if (samplesPerCycle > 512) {
targetRate = 256;
downsampleMod = Math.round(samplesPerCycle / 256);
}
// 记录原始采样率(不降采样)
dataBuf.getSegmentSampleRates()[0] = samplesPerCycle;
dataBuf.getSegmentSampleRates()[0] = targetRate;
log.info("单段数据 - 原始: {}点/周波, 保留原始数据", samplesPerCycle);
int totalSamples = cfgInfo.getTotalSamples();
for (int i = 0; i < totalSamples; i++) {
@@ -948,22 +930,20 @@ public class ComtradeReader {
break;
}
if (i % downsampleMod == 0) {
ByteBuffer bb = ByteBuffer.wrap(buffer);
bb.order(ByteOrder.LITTLE_ENDIAN);
ByteBuffer bb = ByteBuffer.wrap(buffer);
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.getInt();
bb.getInt();
bb.getInt();
bb.getInt();
for (int ch = 0; ch < cfgInfo.getAnalogChannels() && ch < MAX_CH_NUM; ch++) {
short rawValue = bb.getShort();
dataBuf.getSmpData()[ch][sampleIndex] = rawValue;
}
sampleIndex++;
for (int ch = 0; ch < cfgInfo.getAnalogChannels() && ch < MAX_CH_NUM; ch++) {
short rawValue = bb.getShort();
dataBuf.getSmpData()[ch][sampleIndex] = rawValue;
}
sampleIndex++;
}
log.info("单段数据处理完成 - 采样点: {}, 采样率: {}点/周波", sampleIndex, targetRate);
log.info("单段数据处理完成 - 采样点: {}, 采样率: {}点/周波", sampleIndex, samplesPerCycle);
}
}

View File

@@ -17,6 +17,8 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import static com.njcn.gather.tools.comtrade.comparewave.core.Constants.MAX_CH_NUM;
/**
* 波形比对分析服务实现类
*
@@ -418,6 +420,20 @@ public class CompareWaveServiceImpl implements ICompareWaveService {
break;
}
// 检查采样率是否过低(< 128
boolean sourceLowSampleRate = (sourceSampleRate < 128);
boolean targetLowSampleRate = (targetSampleRate < 128);
if (sourceLowSampleRate || targetLowSampleRate) {
log.warn("窗口 {} - 采样率过低(源文件: {}点/周波, 目标文件: {}点/周波, 最小要求128该窗口被丢弃",
window, sourceSampleRate, targetSampleRate);
// 推进位置到下一个窗口
sourceCurrentPos = sourceWindowEnd;
targetCurrentPos = targetWindowEnd;
continue;
}
// 判断源文件窗口是否跨段
int sourceEndSegment = findSegmentIndex(sourceDataBuf, sourceWindowEnd - 1);
boolean sourceCrossSegment = (sourceSegment != sourceEndSegment);
@@ -429,12 +445,14 @@ public class CompareWaveServiceImpl implements ICompareWaveService {
// 如果任一文件跨段,两个文件都丢弃该窗口
if (sourceCrossSegment || targetCrossSegment) {
if (sourceCrossSegment) {
log.warn("窗口 {} - 源文件跨段(段{} -> 段{}),该窗口被丢弃",
window, sourceSegment, sourceEndSegment);
float sourceEndSampleRate = sourceDataBuf.getSegmentSampleRates()[sourceEndSegment];
log.warn("窗口 {} - 源文件跨段(段{}/{}点/周波 -> 段{}/{}点/周波),该窗口被丢弃",
window, sourceSegment, sourceSampleRate, sourceEndSegment, sourceEndSampleRate);
}
if (targetCrossSegment) {
log.warn("窗口 {} - 目标文件跨段(段{} -> 段{}),该窗口被丢弃",
window, targetSegment, targetEndSegment);
float targetEndSampleRate = targetDataBuf.getSegmentSampleRates()[targetEndSegment];
log.warn("窗口 {} - 目标文件跨段(段{}/{}点/周波 -> 段{}/{}点/周波),该窗口被丢弃",
window, targetSegment, targetSampleRate, targetEndSegment, targetEndSampleRate);
}
// 推进位置到下一个窗口
@@ -449,24 +467,16 @@ public class CompareWaveServiceImpl implements ICompareWaveService {
ClockStruct sourceDataTime = calculateWindowTime(sourceStartTime, window);
ClockStruct targetDataTime = calculateWindowTime(targetStartTime, window);
// 计算源文件窗口
float sourceOriginalRate = sourceDataBuf.getSmpRate();
sourceDataBuf.setSmpRate(sourceSampleRate);
sourceDataBuf.setDataPoint(validWindowCount);
PowerQualityCalculator.pqs200msDataCal(sourceDataBuf, sourceDataTime, sourceWindowEnd);
sourceDataBuf.setSmpRate(sourceOriginalRate);
PqsDataStruct sourceResult = sourceDataBuf.getPqData()[validWindowCount];
// 计算源文件窗口(如果采样率>512降采样到256
PqsDataStruct sourceResult = calculateWindowWithDownsampling(
sourceDataBuf, sourceCurrentPos, sourceWindowEnd,
sourceSampleRate, sourceDataTime, validWindowCount);
sourceResults.add(sourceResult);
// 计算目标文件窗口
float targetOriginalRate = targetDataBuf.getSmpRate();
targetDataBuf.setSmpRate(targetSampleRate);
targetDataBuf.setDataPoint(validWindowCount);
PowerQualityCalculator.pqs200msDataCal(targetDataBuf, targetDataTime, targetWindowEnd);
targetDataBuf.setSmpRate(targetOriginalRate);
PqsDataStruct targetResult = targetDataBuf.getPqData()[validWindowCount];
// 计算目标文件窗口(如果采样率>512降采样到256
PqsDataStruct targetResult = calculateWindowWithDownsampling(
targetDataBuf, targetCurrentPos, targetWindowEnd,
targetSampleRate, targetDataTime, validWindowCount);
targetResults.add(targetResult);
log.info("有效窗口 {} (总窗口{}) - 源文件段{}/{}点, 目标文件段{}/{}点, UA: {}/{}, IA: {}/{}",
@@ -501,6 +511,81 @@ public class CompareWaveServiceImpl implements ICompareWaveService {
compareWaveDTO.setTargetResults(targetResults);
}
/**
* 计算窗口电能质量参数(如果采样率>512降采样到256
*
* @param dataBuf 数据缓冲区
* @param windowStart 窗口起始位置
* @param windowEnd 窗口结束位置
* @param sampleRate 窗口采样率(点/周波)
* @param dataTime 时间戳
* @param windowIndex 窗口索引
* @return 计算结果
*/
private PqsDataStruct calculateWindowWithDownsampling(
DataPq dataBuf, int windowStart, int windowEnd,
float sampleRate, ClockStruct dataTime, int windowIndex) {
float originalRate = dataBuf.getSmpRate();
int originalDataPoint = dataBuf.getDataPoint();
try {
// 判断是否需要降采样
if (sampleRate > 512) {
// 需要降采样到256
int downsampleMod = Math.round(sampleRate / 256);
float targetRate = 256;
int windowSamples = windowEnd - windowStart;
int downsampledSamples = (windowSamples + downsampleMod - 1) / downsampleMod;
log.debug("窗口{}降采样: {}点/周波 -> 256点/周波, 模数: {}, 原始{}点 -> {}点",
windowIndex, sampleRate, downsampleMod, windowSamples, downsampledSamples);
// 备份原始数据
int[][] backup = new int[MAX_CH_NUM][windowSamples];
for (int ch = 0; ch < MAX_CH_NUM; ch++) {
System.arraycopy(dataBuf.getSmpData()[ch], windowStart, backup[ch], 0, windowSamples);
}
// 降采样每downsampleMod个点取1个
int downsampledIndex = 0;
for (int i = 0; i < windowSamples; i += downsampleMod) {
for (int ch = 0; ch < MAX_CH_NUM; ch++) {
dataBuf.getSmpData()[ch][windowStart + downsampledIndex] =
dataBuf.getSmpData()[ch][windowStart + i];
}
downsampledIndex++;
}
// 设置降采样后的采样率和窗口结束位置
dataBuf.setSmpRate(targetRate);
dataBuf.setDataPoint(windowIndex);
int downsampledWindowEnd = windowStart + downsampledSamples;
// 计算电能质量参数
PowerQualityCalculator.pqs200msDataCal(dataBuf, dataTime, downsampledWindowEnd);
// 恢复原始数据
for (int ch = 0; ch < MAX_CH_NUM; ch++) {
System.arraycopy(backup[ch], 0, dataBuf.getSmpData()[ch], windowStart, windowSamples);
}
} else {
// 不需要降采样,直接计算
dataBuf.setSmpRate(sampleRate);
dataBuf.setDataPoint(windowIndex);
PowerQualityCalculator.pqs200msDataCal(dataBuf, dataTime, windowEnd);
}
return dataBuf.getPqData()[windowIndex];
} finally {
// 恢复原始设置
dataBuf.setSmpRate(originalRate);
dataBuf.setDataPoint(originalDataPoint);
}
}
/**
* 计算窗口的时间戳
*/