feat(event): 添加暂态事件波形查看与导出功能

- 新增 getTransientEventWave 接口用于查看暂态事件波形
- 新增 exportTransientEventWaves 接口用于批量导出暂态事件波形
- 添加 EventWaveExportParam 参数类支持波形导出
- 在 EventListMapper 中增加 selectTransientDetailsByIds 查询方法
- 更新事件列表查询参数支持毫秒级时间格式
- 移除事件描述模糊查询条件优化查询性能
- 添加波形导出相关的常量和工具类集成
This commit is contained in:
2026-05-18 16:31:01 +08:00
parent 38f910fccd
commit 1ee94208ae
10 changed files with 215 additions and 116 deletions

View File

@@ -50,10 +50,10 @@ webSocket:
steady:
influxdb:
url: http://192.168.1.103:18086
url: http://192.168.1.68:18086
database: pqsbase
username: admin
password: ${STEADY_INFLUXDB_PASSWORD:}
password: 123456
ssl: false
connect-timeout-ms: 5000
read-timeout-ms: 30000

View File

@@ -40,34 +40,29 @@ public class SteadyInfluxQueryComponent {
private final SteadyInfluxDbProperties properties;
public List<SteadyTrendPointVO> queryTrendPoints(SteadyTrendResolvedFieldBO field, LocalDateTime startTime,
LocalDateTime endTime, String bucket, Integer qualityFlag) {
LocalDateTime endTime, Integer qualityFlag) {
validateConfig();
String query = buildTrendQuery(field, startTime, endTime, bucket, qualityFlag);
String query = buildTrendQuery(field, startTime, endTime, qualityFlag);
String body = executeQuery(query);
return parseTrendPoints(body);
}
public String buildTrendQuery(SteadyTrendResolvedFieldBO field, LocalDateTime startTime, LocalDateTime endTime,
String bucket, Integer qualityFlag) {
Integer qualityFlag) {
StringBuilder sql = new StringBuilder();
if (bucket == null || bucket.trim().isEmpty()) {
sql.append("SELECT \"").append(field.getField()).append("\" AS \"value\"");
} else {
sql.append("SELECT mean(\"").append(field.getField()).append("\") AS \"value\"");
}
sql.append("SELECT \"").append(field.getField()).append("\" AS \"value\"");
sql.append(" FROM \"").append(field.getMeasurement()).append("\"");
sql.append(" WHERE time >= '").append(INFLUX_TIME_FORMATTER.format(startTime)).append("'");
sql.append(" AND time <= '").append(INFLUX_TIME_FORMATTER.format(endTime)).append("'");
sql.append(" AND \"LINEID\" = '").append(escapeTagValue(field.getLineId())).append("'");
sql.append(" AND \"PHASIC_TYPE\" = '").append(escapeTagValue(field.getPhase())).append("'");
sql.append(" AND \"line_id\" = '").append(escapeTagValue(field.getLineId())).append("'");
sql.append(" AND \"phasic_type\" = '").append(escapeTagValue(field.getPhase())).append("'");
if (hasValueTypeTag(field.getMeasurement())) {
sql.append(" AND \"value_type\" = '").append(resolveValueType(field.getStatType())).append("'");
}
if (qualityFlag != null) {
sql.append(" AND \"QUALITYFLAG\" = '").append(qualityFlag).append("'");
}
if (bucket != null && !bucket.trim().isEmpty()) {
sql.append(" GROUP BY time(").append(bucket.trim()).append(") fill(none)");
} else {
sql.append(" ORDER BY time ASC");
sql.append(" AND \"quality_flag\" = '").append(qualityFlag).append("'");
}
sql.append(" ORDER BY time ASC");
return sql.toString();
}
@@ -165,6 +160,17 @@ public class SteadyInfluxQueryComponent {
return value == null ? "" : value.replace("\\", "\\\\").replace("'", "\\'");
}
private String resolveValueType(String statType) {
if (statType == null || statType.trim().isEmpty()) {
return "AVG";
}
return statType.trim().toUpperCase();
}
private boolean hasValueTypeTag(String measurement) {
return !"data_flicker".equals(measurement) && !"data_fluc".equals(measurement) && !"data_plt".equals(measurement);
}
private String trimRightSlash(String value) {
String text = value.trim();
while (text.endsWith("/")) {

View File

@@ -6,8 +6,6 @@ import com.njcn.gather.steady.datavie.pojo.bo.SteadyTrendIndicatorDefinitionBO;
import com.njcn.gather.steady.datavie.pojo.bo.SteadyTrendResolvedFieldBO;
import com.njcn.gather.steady.datavie.pojo.bo.SteadyTrendSeriesFieldBO;
import com.njcn.gather.steady.datavie.pojo.param.SteadyTrendQueryParam;
import com.njcn.gather.tool.adddata.component.AddDataTableRegistry;
import com.njcn.gather.tool.adddata.pojo.bo.AddDataTableDefinition;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
@@ -32,7 +30,6 @@ public class SteadyTrendFieldResolver {
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private final SteadyTrendIndicatorCatalog indicatorCatalog;
private final AddDataTableRegistry addDataTableRegistry;
public List<SteadyTrendResolvedFieldBO> resolveFields(SteadyTrendQueryParam param) {
validateBasicParam(param);
@@ -80,9 +77,7 @@ public class SteadyTrendFieldResolver {
}
List<SteadyTrendResolvedFieldBO> result = new ArrayList<SteadyTrendResolvedFieldBO>();
for (SteadyTrendSeriesFieldBO seriesField : indicator.getSeriesFields()) {
String field = resolveStatField(seriesField.getField(), statType);
validateColumn(indicator.getTableName(), field);
result.add(buildResolvedField(lineId, indicator, phase, statType, field, seriesField.getName()));
result.add(buildResolvedField(lineId, indicator, phase, statType, seriesField.getField(), seriesField.getName()));
}
return result;
}
@@ -101,9 +96,7 @@ public class SteadyTrendFieldResolver {
if (order < indicator.getHarmonicOrderStart() || order > indicator.getHarmonicOrderEnd()) {
throw fail("谐波次数只能在 " + indicator.getHarmonicOrderStart() + "" + indicator.getHarmonicOrderEnd() + " 之间");
}
String baseField = indicator.getHarmonicFieldPrefix() + "_" + order;
String field = resolveStatField(baseField, statType);
validateColumn(indicator.getTableName(), field);
String field = indicator.getHarmonicFieldPrefix() + "_" + order;
result.add(buildResolvedField(lineId, indicator, phase, statType, field, order + "" + indicator.getName()));
}
return result;
@@ -177,25 +170,6 @@ public class SteadyTrendFieldResolver {
}
}
private String resolveStatField(String baseField, String statType) {
if ("AVG".equals(statType)) {
return baseField;
}
return baseField + "_" + statType;
}
private void validateColumn(String tableName, String field) {
AddDataTableDefinition definition;
try {
definition = addDataTableRegistry.getDefinition(tableName);
} catch (IllegalArgumentException ex) {
throw fail("稳态数据表不支持:" + tableName);
}
if (!definition.getColumns().contains(field)) {
throw fail("稳态趋势字段不支持:" + tableName + "." + field);
}
}
private List<String> normalizeTextList(List<String> values) {
if (values == null || values.isEmpty()) {
return new ArrayList<String>();

View File

@@ -28,32 +28,31 @@ public class SteadyTrendIndicatorCatalog {
public SteadyTrendIndicatorCatalog() {
List<SteadyTrendIndicatorDefinitionBO> result = new ArrayList<SteadyTrendIndicatorDefinitionBO>();
result.add(indicator("V_RMS", "相电压有效值", "VOLTAGE", "电压趋势", "data_v", ABC_PHASES,
fields(field("RMS", "相电压有效值")), FULL_STATS, "V"));
fields(field("rms", "相电压有效值")), FULL_STATS, "V"));
result.add(indicator("V_LINE_RMS", "线电压有效值", "VOLTAGE", "电压趋势", "data_v", T_PHASE,
fields(field("RMSAB", "AB线电压"), field("RMSBC", "BC线电压"), field("RMSCA", "CA线电压")),
fields(field("rms_lvr", "线电压有效值")),
FULL_STATS, "V"));
result.add(indicator("FREQ", "频率", "FREQUENCY", "频率趋势", "data_v", T_PHASE,
fields(field("FREQ", "频率")), FULL_STATS, "Hz"));
fields(field("freq", "频率")), FULL_STATS, "Hz"));
result.add(indicator("V_THD", "电压总谐波畸变率", "HARMONIC", "谐波趋势", "data_v", ABC_PHASES,
fields(field("V_THD", "电压总谐波畸变率")), FULL_STATS, "%"));
fields(field("v_thd", "电压总谐波畸变率")), FULL_STATS, "%"));
result.add(indicator("I_RMS", "电流有效值", "CURRENT", "电流趋势", "data_i", ABC_PHASES,
fields(field("RMS", "电流有效值")), FULL_STATS, "A"));
fields(field("rms", "电流有效值")), FULL_STATS, "A"));
result.add(indicator("I_THD", "电流总谐波畸变率", "HARMONIC", "谐波趋势", "data_i", ABC_PHASES,
fields(field("I_THD", "电流总谐波畸变率")), FULL_STATS, "%"));
result.add(harmonic("V_HARMONIC", "电压谐波幅值", "data_harmphasic_v", "V", "V"));
result.add(harmonic("I_HARMONIC", "电流谐波幅值", "data_harmphasic_i", "I", "A"));
result.add(harmonic("V_HARMONIC_RATE", "电压谐波含有率", "data_harmrate_v", "V", "%"));
result.add(harmonic("I_HARMONIC_RATE", "电流谐波含有率", "data_harmrate_i", "I", "%"));
result.add(harmonic("I_INTER_HARMONIC", "间谐波电流", "data_inharm_i", "I", "A"));
result.add(harmonicPower("P_HARMONIC_POWER", "功谐波功率", "data_harmpower_p", "P", "kW"));
result.add(harmonicPower("Q_HARMONIC_POWER", "无功谐波功率", "data_harmpower_q", "Q", "kvar"));
result.add(harmonicPower("S_HARMONIC_POWER", "视在谐波功率", "data_harmpower_s", "S", "kVA"));
fields(field("i_thd", "电流总谐波畸变率")), FULL_STATS, "%"));
result.add(harmonic("V_HARMONIC", "电压谐波幅值", "data_harmphasic_v", "v", "V"));
result.add(harmonic("I_HARMONIC", "电流谐波幅值", "data_harmphasic_i", "i", "A"));
result.add(harmonic("V_HARMONIC_RATE", "电压谐波含有率", "data_harmrate_v", "v", "%"));
result.add(harmonic("I_INTER_HARMONIC", "间谐波电流", "data_inharm_i", "i", "A"));
result.add(harmonicPower("P_HARMONIC_POWER", "有功谐波功率", "data_harmpower_p", "p", "kW"));
result.add(harmonicPower("Q_HARMONIC_POWER", "功谐波功率", "data_harmpower_q", "q", "kvar"));
result.add(harmonicPower("S_HARMONIC_POWER", "视在谐波功率", "data_harmpower_s", "s", "kVA"));
result.add(indicator("FLUC", "电压波动", "FLICKER", "闪变趋势", "data_fluc", T_PHASE,
fields(field("FLUC", "电压波动")), AVG_ONLY, "%"));
fields(field("fluc", "电压波动")), AVG_ONLY, "%"));
result.add(indicator("PST", "短时闪变", "FLICKER", "闪变趋势", "data_flicker", T_PHASE,
fields(field("PST", "短时闪变")), AVG_ONLY, ""));
fields(field("pst", "短时闪变")), AVG_ONLY, ""));
result.add(indicator("PLT", "长时闪变", "FLICKER", "闪变趋势", "data_plt", T_PHASE,
fields(field("PLT", "长时闪变")), AVG_ONLY, ""));
fields(field("plt", "长时闪变")), AVG_ONLY, ""));
indicators = Collections.unmodifiableList(result);
Map<String, SteadyTrendIndicatorDefinitionBO> map = new LinkedHashMap<String, SteadyTrendIndicatorDefinitionBO>();

View File

@@ -29,9 +29,6 @@ public class SteadyTrendQueryParam {
@ApiModelProperty("结束时间,格式 yyyy-MM-dd HH:mm:ss")
private String timeEnd;
@ApiModelProperty("分桶粒度,如 1m、5m、10m、30m、1h")
private String bucket;
@ApiModelProperty("质量标识")
private Integer qualityFlag;

View File

@@ -18,8 +18,6 @@ public class SteadyTrendQueryVO implements Serializable {
private Boolean sampled;
private String bucket;
private Integer sourcePointCount;
private Integer displayPointCount;

View File

@@ -1,7 +1,5 @@
package com.njcn.gather.steady.datavie.service.impl;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.gather.steady.datavie.component.SteadyInfluxQueryComponent;
import com.njcn.gather.steady.datavie.component.SteadyTrendFieldResolver;
import com.njcn.gather.steady.datavie.pojo.bo.SteadyTrendResolvedFieldBO;
@@ -21,7 +19,6 @@ import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -43,19 +40,18 @@ public class SteadyDataViewTrendServiceImpl implements SteadyDataViewTrendServic
@Override
public SteadyTrendQueryVO queryTrend(SteadyTrendQueryParam param) {
return queryTrendInternal(param, true);
return queryTrendInternal(param);
}
@Override
public SteadyTrendQueryVO queryTrendDay(SteadyTrendQueryParam param) {
return queryTrendInternal(param, true);
return queryTrendInternal(param);
}
@Override
public SteadyTrendSummaryVO summarizeTrend(SteadyTrendQueryParam param) {
SteadyTrendQueryParam summaryParam = copyParam(param);
summaryParam.setBucket(null);
SteadyTrendQueryVO trend = queryTrendInternal(summaryParam, false);
SteadyTrendQueryVO trend = queryTrendInternal(summaryParam);
SteadyTrendSummaryVO result = new SteadyTrendSummaryVO();
for (SteadyTrendSeriesVO series : trend.getSeries()) {
result.getItems().add(buildSummaryItem(series));
@@ -63,20 +59,18 @@ public class SteadyDataViewTrendServiceImpl implements SteadyDataViewTrendServic
return result;
}
private SteadyTrendQueryVO queryTrendInternal(SteadyTrendQueryParam param, boolean autoBucket) {
private SteadyTrendQueryVO queryTrendInternal(SteadyTrendQueryParam param) {
LocalDateTime startTime = fieldResolver.parseRequiredTime(param == null ? null : param.getTimeStart(), "开始时间不能为空");
LocalDateTime endTime = fieldResolver.parseRequiredTime(param == null ? null : param.getTimeEnd(), "结束时间不能为空");
List<SteadyTrendResolvedFieldBO> fields = fieldResolver.resolveFields(param);
enrichLineNames(fields);
String bucket = autoBucket ? resolveBucket(param.getBucket(), startTime, endTime) : null;
SteadyTrendQueryVO result = new SteadyTrendQueryVO();
result.setBucket(bucket);
result.setSampled(bucket != null);
result.setSampled(false);
result.setLoadableDays(resolveLoadableDays(startTime, endTime));
int displayPointCount = 0;
for (SteadyTrendResolvedFieldBO field : fields) {
List<SteadyTrendPointVO> points = influxQueryComponent.queryTrendPoints(field, startTime, endTime, bucket, param.getQualityFlag());
List<SteadyTrendPointVO> points = influxQueryComponent.queryTrendPoints(field, startTime, endTime, param.getQualityFlag());
displayPointCount += points.size();
result.getSeries().add(buildSeries(field, points));
}
@@ -143,27 +137,6 @@ public class SteadyDataViewTrendServiceImpl implements SteadyDataViewTrendServic
return item;
}
private String resolveBucket(String requestBucket, LocalDateTime startTime, LocalDateTime endTime) {
String bucket = trimToNull(requestBucket);
if (bucket != null) {
if (!bucket.matches("^[1-9][0-9]*(m|h|d)$")) {
throw fail("分桶粒度仅支持 m、h、d例如 10m、1h");
}
return bucket;
}
long hours = ChronoUnit.HOURS.between(startTime, endTime);
if (hours < 6) {
return "1m";
}
if (hours <= 24) {
return "10m";
}
if (hours <= 24 * 7) {
return "30m";
}
return "1h";
}
private List<String> resolveLoadableDays(LocalDateTime startTime, LocalDateTime endTime) {
List<String> result = new ArrayList<String>();
LocalDate date = startTime.toLocalDate();
@@ -185,7 +158,6 @@ public class SteadyDataViewTrendServiceImpl implements SteadyDataViewTrendServic
target.setStatTypes(copyList(source.getStatTypes()));
target.setTimeStart(source.getTimeStart());
target.setTimeEnd(source.getTimeEnd());
target.setBucket(source.getBucket());
target.setQualityFlag(source.getQualityFlag());
target.setHarmonicOrders(source.getHarmonicOrders() == null ? Collections.<Integer>emptyList() : new ArrayList<Integer>(source.getHarmonicOrders()));
return target;
@@ -203,7 +175,4 @@ public class SteadyDataViewTrendServiceImpl implements SteadyDataViewTrendServic
return trimmed.isEmpty() ? null : trimmed;
}
private BusinessException fail(String message) {
return new BusinessException(CommonResponseEnum.FAIL, message);
}
}

View File

@@ -0,0 +1,94 @@
package com.njcn.gather.steady.datavie.component;
import com.njcn.gather.steady.datavie.config.SteadyInfluxDbProperties;
import com.njcn.gather.steady.datavie.pojo.bo.SteadyTrendResolvedFieldBO;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
/**
* 稳态趋势 InfluxQL 构造契约测试。
*/
class SteadyInfluxQueryComponentTest {
@Test
void shouldBuildRawPointQueryWithoutTimeBucketAggregation() {
SteadyInfluxQueryComponent component = new SteadyInfluxQueryComponent(new SteadyInfluxDbProperties());
SteadyTrendResolvedFieldBO field = new SteadyTrendResolvedFieldBO();
field.setMeasurement("data_v");
field.setField("RMS");
field.setLineId("line-001");
field.setPhase("A");
String query = component.buildTrendQuery(field,
LocalDateTime.of(2026, 5, 1, 0, 0, 0),
LocalDateTime.of(2026, 5, 1, 23, 59, 59),
1);
Assertions.assertTrue(query.startsWith("SELECT \"RMS\" AS \"value\""), "趋势查询应读取原始字段值");
Assertions.assertTrue(query.endsWith(" ORDER BY time ASC"), "趋势查询应按原始时间升序返回");
Assertions.assertFalse(query.contains("mean("), "趋势查询不应按颗粒度聚合");
Assertions.assertFalse(query.contains("GROUP BY time"), "趋势查询不应生成时间分桶");
}
@Test
void shouldBuildQueryWithActualInfluxTagsAndValueType() {
SteadyInfluxQueryComponent component = new SteadyInfluxQueryComponent(new SteadyInfluxDbProperties());
SteadyTrendResolvedFieldBO field = new SteadyTrendResolvedFieldBO();
field.setMeasurement("data_v");
field.setField("rms");
field.setLineId("00B78D00A8791");
field.setPhase("A");
field.setStatType("AVG");
String query = component.buildTrendQuery(field,
LocalDateTime.of(2026, 5, 1, 0, 0, 0),
LocalDateTime.of(2026, 5, 1, 23, 59, 59),
0);
Assertions.assertTrue(query.contains("\"line_id\" = '00B78D00A8791'"));
Assertions.assertTrue(query.contains("\"phasic_type\" = 'A'"));
Assertions.assertTrue(query.contains("\"quality_flag\" = '0'"));
Assertions.assertTrue(query.contains("\"value_type\" = 'AVG'"));
Assertions.assertFalse(query.contains("\"LINEID\""));
Assertions.assertFalse(query.contains("\"PHASIC_TYPE\""));
Assertions.assertFalse(query.contains("\"QUALITYFLAG\""));
}
@Test
void shouldDefaultValueTypeToUpperAvg() {
SteadyInfluxQueryComponent component = new SteadyInfluxQueryComponent(new SteadyInfluxDbProperties());
SteadyTrendResolvedFieldBO field = new SteadyTrendResolvedFieldBO();
field.setMeasurement("data_v");
field.setField("rms");
field.setLineId("0798e5a9a72ebbc4daaa4a631701c813");
field.setPhase("A");
String query = component.buildTrendQuery(field,
LocalDateTime.of(2026, 5, 1, 0, 0, 0),
LocalDateTime.of(2026, 5, 1, 23, 59, 59),
0);
Assertions.assertTrue(query.contains("\"value_type\" = 'AVG'"));
}
@Test
void shouldSkipValueTypeWhenMeasurementHasNoValueTypeTag() {
SteadyInfluxQueryComponent component = new SteadyInfluxQueryComponent(new SteadyInfluxDbProperties());
SteadyTrendResolvedFieldBO field = new SteadyTrendResolvedFieldBO();
field.setMeasurement("data_fluc");
field.setField("fluc");
field.setLineId("0798e5a9a72ebbc4daaa4a631701c813");
field.setPhase("T");
field.setStatType("AVG");
String query = component.buildTrendQuery(field,
LocalDateTime.of(2026, 5, 1, 0, 0, 0),
LocalDateTime.of(2026, 5, 1, 23, 59, 59),
0);
Assertions.assertFalse(query.contains("\"value_type\""));
Assertions.assertTrue(query.contains("\"quality_flag\" = '0'"));
}
}

View File

@@ -3,7 +3,6 @@ package com.njcn.gather.steady.datavie.component;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.gather.steady.datavie.pojo.bo.SteadyTrendResolvedFieldBO;
import com.njcn.gather.steady.datavie.pojo.param.SteadyTrendQueryParam;
import com.njcn.gather.tool.adddata.component.AddDataTableRegistry;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -20,10 +19,8 @@ class SteadyTrendFieldResolverTest {
private SteadyTrendFieldResolver resolver;
@BeforeEach
void setUp() throws Exception {
AddDataTableRegistry tableRegistry = new AddDataTableRegistry();
tableRegistry.afterPropertiesSet();
resolver = new SteadyTrendFieldResolver(new SteadyTrendIndicatorCatalog(), tableRegistry);
void setUp() {
resolver = new SteadyTrendFieldResolver(new SteadyTrendIndicatorCatalog());
}
@Test
@@ -41,6 +38,21 @@ class SteadyTrendFieldResolverTest {
Assertions.assertEquals(Arrays.asList("A", "B", "C"), phases);
}
@Test
void shouldResolveVoltageRmsToActualInfluxField() {
SteadyTrendQueryParam param = new SteadyTrendQueryParam();
param.setLineIds(Arrays.asList("00B78D00A8791"));
param.setIndicatorCodes(Arrays.asList("V_RMS"));
param.setStatTypes(Arrays.asList("AVG"));
param.setTimeStart("2026-05-01 00:00:00");
param.setTimeEnd("2026-05-01 01:00:00");
List<SteadyTrendResolvedFieldBO> fields = resolver.resolveFields(param);
Assertions.assertEquals("rms", fields.get(0).getField());
Assertions.assertEquals("00B78D00A8791|V_RMS|A|AVG|rms", fields.get(0).getSeriesKey());
}
@Test
void shouldExpandTotalPhaseIndicatorWithoutRequestPhaseFilter() {
SteadyTrendQueryParam param = new SteadyTrendQueryParam();
@@ -52,11 +64,35 @@ class SteadyTrendFieldResolverTest {
List<SteadyTrendResolvedFieldBO> fields = resolver.resolveFields(param);
Assertions.assertEquals(3, fields.size());
Assertions.assertEquals(1, fields.size());
Assertions.assertEquals("T", fields.get(0).getPhase());
Assertions.assertEquals("RMSAB", fields.get(0).getField());
Assertions.assertEquals("RMSBC", fields.get(1).getField());
Assertions.assertEquals("RMSCA", fields.get(2).getField());
Assertions.assertEquals("rms_lvr", fields.get(0).getField());
}
@Test
void shouldResolveCommonIndicatorsToActualInfluxFields() {
Assertions.assertEquals("freq", resolveSingleField("FREQ"));
Assertions.assertEquals("v_thd", resolveSingleField("V_THD"));
Assertions.assertEquals("rms", resolveSingleField("I_RMS"));
Assertions.assertEquals("i_thd", resolveSingleField("I_THD"));
Assertions.assertEquals("fluc", resolveSingleField("FLUC"));
Assertions.assertEquals("pst", resolveSingleField("PST"));
Assertions.assertEquals("plt", resolveSingleField("PLT"));
}
@Test
void shouldExposeActualInfluxFieldsInIndicatorCatalog() {
SteadyTrendIndicatorCatalog catalog = new SteadyTrendIndicatorCatalog();
Assertions.assertEquals("rms", catalog.getIndicator("V_RMS").getSeriesFields().get(0).getField());
Assertions.assertEquals("rms_lvr", catalog.getIndicator("V_LINE_RMS").getSeriesFields().get(0).getField());
Assertions.assertEquals("freq", catalog.getIndicator("FREQ").getSeriesFields().get(0).getField());
Assertions.assertEquals("v_thd", catalog.getIndicator("V_THD").getSeriesFields().get(0).getField());
Assertions.assertEquals("rms", catalog.getIndicator("I_RMS").getSeriesFields().get(0).getField());
Assertions.assertEquals("i_thd", catalog.getIndicator("I_THD").getSeriesFields().get(0).getField());
Assertions.assertEquals("fluc", catalog.getIndicator("FLUC").getSeriesFields().get(0).getField());
Assertions.assertEquals("pst", catalog.getIndicator("PST").getSeriesFields().get(0).getField());
Assertions.assertEquals("plt", catalog.getIndicator("PLT").getSeriesFields().get(0).getField());
}
@Test
@@ -87,9 +123,34 @@ class SteadyTrendFieldResolverTest {
Assertions.assertEquals(6, fields.size());
Assertions.assertEquals("A", fields.get(0).getPhase());
Assertions.assertEquals("V_3_MAX", fields.get(0).getField());
Assertions.assertEquals("V_5_MAX", fields.get(1).getField());
Assertions.assertEquals("v_3", fields.get(0).getField());
Assertions.assertEquals("v_5", fields.get(1).getField());
Assertions.assertEquals("B", fields.get(2).getPhase());
Assertions.assertEquals("C", fields.get(4).getPhase());
}
@Test
void shouldResolveHarmonicPowerToActualInfluxField() {
SteadyTrendQueryParam param = new SteadyTrendQueryParam();
param.setLineIds(Arrays.asList("line-001"));
param.setIndicatorCodes(Arrays.asList("P_HARMONIC_POWER"));
param.setStatTypes(Arrays.asList("CP95"));
param.setHarmonicOrders(Arrays.asList(3));
param.setTimeStart("2026-05-01 00:00:00");
param.setTimeEnd("2026-05-01 01:00:00");
List<SteadyTrendResolvedFieldBO> fields = resolver.resolveFields(param);
Assertions.assertEquals("p_3", fields.get(0).getField());
}
private String resolveSingleField(String indicatorCode) {
SteadyTrendQueryParam param = new SteadyTrendQueryParam();
param.setLineIds(Arrays.asList("line-001"));
param.setIndicatorCodes(Arrays.asList(indicatorCode));
param.setStatTypes(Arrays.asList("AVG"));
param.setTimeStart("2026-05-01 00:00:00");
param.setTimeEnd("2026-05-01 01:00:00");
return resolver.resolveFields(param).get(0).getField();
}
}

View File

@@ -16,4 +16,5 @@ class SteadyTrendQueryParamTest {
Assertions.assertNotEquals("phases", field.getName(), "趋势检索请求不再携带相别条件");
}
}
}