波形解析相关
This commit is contained in:
266
tools/wave-tool/PARSE_COMTRADE_API.md
Normal file
266
tools/wave-tool/PARSE_COMTRADE_API.md
Normal file
@@ -0,0 +1,266 @@
|
||||
# parseComtrade API 文档
|
||||
|
||||
## 1. 接口概述
|
||||
|
||||
- 接口名称:解析 COMTRADE 波形文件
|
||||
- Controller:[WaveController.java](D:/Work/SourceCode/CN_Tool/tools/wave-tool/src/main/java/com/njcn/gather/tool/wave/controller/WaveController.java)
|
||||
- 方法:`parseComtrade`
|
||||
- 请求路径:`POST /wave/parseComtrade`
|
||||
- Content-Type:`multipart/form-data`
|
||||
- 返回类型:`HttpResult<WaveComtradeResultVO>`
|
||||
|
||||
用途说明:
|
||||
|
||||
- 上传一组 COMTRADE `cfg/dat` 文件
|
||||
- 解析原始波形数据
|
||||
- 按请求决定是否补充 RMS 数据、前端查看明细和特征值结果
|
||||
|
||||
## 2. 请求参数
|
||||
|
||||
### 2.1 文件参数
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `cfgFile` | file | 是 | COMTRADE 配置文件 `.cfg` |
|
||||
| `datFile` | file | 是 | COMTRADE 数据文件 `.dat` |
|
||||
|
||||
### 2.2 表单参数
|
||||
|
||||
参数定义来源:[WaveComtradeParseParam.java](D:/Work/SourceCode/CN_Tool/tools/wave-tool/src/main/java/com/njcn/gather/tool/wave/pojo/param/WaveComtradeParseParam.java)
|
||||
|
||||
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `parseType` | integer | 否 | `1` | 解析类型:`0` 高级算法采样率 32-128,`1` 普通展示,`2` App 抽点,`3` 原始波形 |
|
||||
| `ptType` | integer | 否 | `0` | PT 接线方式:`0` 星形,`1` 三角,`2` 开口三角 |
|
||||
| `pt` | number | 否 | `1` | PT 变比 |
|
||||
| `ct` | number | 否 | `1` | CT 变比 |
|
||||
| `monitorName` | string | 否 | `未命名测点` | 测点名称 |
|
||||
| `calculateRms` | boolean | 否 | `true` | 是否计算 RMS |
|
||||
| `buildDetails` | boolean | 否 | `true` | 是否构建前端查看明细 |
|
||||
| `calculateEigenvalue` | boolean | 否 | `false` | 是否计算特征值 |
|
||||
| `dynamicThreshold` | boolean | 否 | `true` | 特征值是否使用浮动门槛 |
|
||||
|
||||
## 3. 请求示例
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:8080/wave/parseComtrade" \
|
||||
-F "cfgFile=@D:/00-B7-8D-00-E4-09/1_20260321_201458_748.CFG" \
|
||||
-F "datFile=@D:/00-B7-8D-00-E4-09/1_20260321_201458_748.DAT" \
|
||||
-F "parseType=1" \
|
||||
-F "ptType=0" \
|
||||
-F "pt=1" \
|
||||
-F "ct=1" \
|
||||
-F "monitorName=监测点1" \
|
||||
-F "calculateRms=true" \
|
||||
-F "buildDetails=true" \
|
||||
-F "calculateEigenvalue=true" \
|
||||
-F "dynamicThreshold=true"
|
||||
```
|
||||
|
||||
## 4. 响应结构
|
||||
|
||||
### 4.1 外层响应
|
||||
|
||||
Controller 返回的是 `HttpResult<WaveComtradeResultVO>`。当前仓库内未展开 `HttpResult` 类型源码,本接口文档只对业务 `data` 部分做精确定义。
|
||||
|
||||
业务数据类型来源:[WaveComtradeResultVO.java](D:/Work/SourceCode/CN_Tool/tools/wave-tool/src/main/java/com/njcn/gather/tool/wave/pojo/vo/WaveComtradeResultVO.java)
|
||||
|
||||
### 4.2 data 字段定义
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `waveData` | object | 波形基础数据 |
|
||||
| `waveDataDetails` | array | 前端查看明细,`buildDetails=true` 时返回 |
|
||||
| `eigenvalues` | array | 特征值结果,`calculateEigenvalue=true` 时返回 |
|
||||
|
||||
## 5. 业务对象说明
|
||||
|
||||
### 5.1 waveData
|
||||
|
||||
定义来源:[WaveDataDTO.java](D:/Work/SourceCode/CN_Tool/tools/wave-tool/src/main/java/com/njcn/gather/tool/wave/pojo/dto/WaveDataDTO.java)
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `comtradeCfgDTO` | object | CFG 解析结果 |
|
||||
| `waveTitle` | array<string> | 波形标题,例如 `["Time","UA相","UB相"]` |
|
||||
| `channelNames` | array<string> | 通道名称列表 |
|
||||
| `listWaveData` | array<array<number>> | 原始波形数据,首列为时间,后续列为相电压/电流值 |
|
||||
| `listRmsData` | array<array<number>> | RMS 波形数据,`calculateRms=true` 时可用 |
|
||||
| `listRmsMinData` | array<array<number>> | RMS 最小值摘要 |
|
||||
| `iPhasic` | integer | 相别数量 |
|
||||
| `ptType` | integer | PT 接线方式 |
|
||||
| `pt` | number | PT 变比 |
|
||||
| `ct` | number | CT 变比 |
|
||||
| `time` | string | 事件发生时刻 |
|
||||
| `monitorName` | string | 测点名称 |
|
||||
|
||||
### 5.2 comtradeCfgDTO
|
||||
|
||||
定义来源:[ComtradeCfgDTO.java](D:/Work/SourceCode/CN_Tool/tools/wave-tool/src/main/java/com/njcn/gather/tool/wave/pojo/dto/ComtradeCfgDTO.java)
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `nChannelNum` | integer | 通道总数 |
|
||||
| `nPhasic` | integer | 相别数量 |
|
||||
| `nAnalogNum` | integer | 模拟量通道数 |
|
||||
| `nDigitalNum` | integer | 开关量通道数 |
|
||||
| `timeStart` | string/date | 录波开始时间 |
|
||||
| `timeTrige` | string/date | 触发时间 |
|
||||
| `lstAnalogDTO` | array | 模拟量通道配置 |
|
||||
| `lstDigitalDTO` | array | 开关量通道配置 |
|
||||
| `nRates` | integer | 采样率分段数 |
|
||||
| `lstRate` | array | 采样率分段配置 |
|
||||
| `firstTime` | string/date | 首个触发时间对象 |
|
||||
| `firstMs` | integer | 首个触发毫秒值 |
|
||||
| `nPush` | integer | 触发前推点数 |
|
||||
| `finalSampleRate` | integer | 最终采样率 |
|
||||
| `nAllWaveNum` | integer | 总周波数 |
|
||||
| `strBinType` | string | 文件编码类型,例如 `BINARY` |
|
||||
|
||||
### 5.3 waveDataDetails
|
||||
|
||||
定义来源:[WaveDataDetail.java](D:/Work/SourceCode/CN_Tool/tools/wave-tool/src/main/java/com/njcn/gather/tool/wave/pojo/bo/WaveDataDetail.java)
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `instantData` | object | 瞬时波形数据 |
|
||||
| `rmsData` | object | RMS 波形数据 |
|
||||
| `a` | string | A 相名称 |
|
||||
| `b` | string | B 相名称 |
|
||||
| `c` | string | C 相名称 |
|
||||
| `channelName` | string | 通道名称 |
|
||||
| `unit` | string | 单位 |
|
||||
| `isOpen` | boolean | 是否开口三角模式 |
|
||||
| `title` | string | 当前图标题 |
|
||||
| `colors` | array<string> | 曲线颜色 |
|
||||
|
||||
其中 `instantData` 和 `rmsData` 结构一致,定义分别来自:
|
||||
|
||||
- [InstantData.java](D:/Work/SourceCode/CN_Tool/tools/wave-tool/src/main/java/com/njcn/gather/tool/wave/pojo/bo/InstantData.java)
|
||||
- [RmsData.java](D:/Work/SourceCode/CN_Tool/tools/wave-tool/src/main/java/com/njcn/gather/tool/wave/pojo/bo/RmsData.java)
|
||||
|
||||
公共字段:
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `max` | number | 当前曲线最大值 |
|
||||
| `min` | number | 当前曲线最小值 |
|
||||
| `aValue` | array<array<number>> | A 相点位 |
|
||||
| `bValue` | array<array<number>> | B 相点位 |
|
||||
| `cValue` | array<array<number>> | C 相点位 |
|
||||
|
||||
### 5.4 eigenvalues
|
||||
|
||||
定义来源:[EigenvalueDTO.java](D:/Work/SourceCode/CN_Tool/tools/wave-tool/src/main/java/com/njcn/gather/tool/wave/pojo/dto/EigenvalueDTO.java)
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `amplitude` | number | 特征幅值百分比 |
|
||||
| `residualVoltage` | number | 残余电压 |
|
||||
| `ratedVoltage` | number | 额定电压 |
|
||||
| `durationTime` | number | 持续时间 |
|
||||
|
||||
## 6. 成功响应示例
|
||||
|
||||
以下示例基于真实样本文件联测结果整理,长数组做了截断展示。
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "SUCCESS",
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"waveData": {
|
||||
"comtradeCfgDTO": {
|
||||
"nChannelNum": 6,
|
||||
"nPhasic": 3,
|
||||
"nAnalogNum": 6,
|
||||
"nDigitalNum": 0,
|
||||
"timeStart": "2026-03-21 20:14:58.648",
|
||||
"timeTrige": "2026-03-21 20:14:58.748",
|
||||
"nRates": 1,
|
||||
"firstMs": 748,
|
||||
"nPush": 100,
|
||||
"finalSampleRate": 512,
|
||||
"nAllWaveNum": 30,
|
||||
"strBinType": "BINARY"
|
||||
},
|
||||
"waveTitle": ["Time", "UA相", "UB相", "UC相", "IA相", "IB相", "IC相"],
|
||||
"channelNames": ["/", "U1", "U2", "U3", "I1", "I2", "I3"],
|
||||
"listWaveData": {
|
||||
"count": 15616,
|
||||
"first": [-100.0, -146.56, -76.9, -76.9, -0.13, 0.01, -0.2],
|
||||
"last": [509.96, 148.02, 69.73, 69.75, 0.16, 0.01, 0.15]
|
||||
},
|
||||
"listRmsData": {
|
||||
"count": 15616,
|
||||
"first": [-100.0, 104.94, 104.22, 104.23, 0.27, 0.01, 0.28],
|
||||
"last": [509.96, 105.6, 105.1, 105.12, 0.24, 0.01, 0.24]
|
||||
},
|
||||
"listRmsMinData": [
|
||||
[40.74, 41.2],
|
||||
[362.19, 0.01]
|
||||
],
|
||||
"iPhasic": 3,
|
||||
"ptType": 0,
|
||||
"pt": 1.0,
|
||||
"ct": 1.0,
|
||||
"time": "2026-03-21 20:14:58.748",
|
||||
"monitorName": "监测点1"
|
||||
},
|
||||
"waveDataDetails": [
|
||||
{
|
||||
"channelName": "U1",
|
||||
"unit": "kV",
|
||||
"a": "A相",
|
||||
"b": "B相",
|
||||
"c": "C相",
|
||||
"isOpen": false
|
||||
},
|
||||
{
|
||||
"channelName": "I1",
|
||||
"unit": "A",
|
||||
"a": "A相",
|
||||
"b": "B相",
|
||||
"c": "C相",
|
||||
"isOpen": false
|
||||
}
|
||||
],
|
||||
"eigenvalues": [
|
||||
{
|
||||
"amplitude": 0.3926178,
|
||||
"residualVoltage": 41.200005,
|
||||
"ratedVoltage": 104.936676,
|
||||
"durationTime": 48.632812
|
||||
},
|
||||
{
|
||||
"amplitude": 0.4067544,
|
||||
"residualVoltage": 42.390152,
|
||||
"ratedVoltage": 104.21559,
|
||||
"durationTime": 54.492188
|
||||
},
|
||||
{
|
||||
"amplitude": 0.40674016,
|
||||
"residualVoltage": 42.396355,
|
||||
"ratedVoltage": 104.2345,
|
||||
"durationTime": 54.492188
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 7. 失败场景
|
||||
|
||||
基于当前代码,常见失败场景包括:
|
||||
|
||||
| 场景 | 说明 |
|
||||
| --- | --- |
|
||||
| `cfgFile` 或 `datFile` 未上传 | 返回业务异常,提示“cfg 或 dat 文件不能为空” |
|
||||
| CFG 文件格式错误 | 返回 CFG 解析失败 |
|
||||
| DAT 文件为空或格式错误 | 返回 DAT 解析失败 |
|
||||
| COMTRADE 解析过程中出现异常 | 返回“COMTRADE 波形解析失败” |
|
||||
|
||||
## 8. 备注
|
||||
|
||||
- 当前接口已经移除图片生成相关参数,不再支持 `generateInstantImage`、`generateRmsImage` 等旧字段。
|
||||
- 当前接口文档只覆盖 `parseComtrade`,其他波形文本解析接口请单独编写。
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,122 @@
|
||||
package com.njcn.gather.tool.wave.component;
|
||||
|
||||
import com.njcn.gather.tool.wave.pojo.dto.EigenvalueDTO;
|
||||
import com.njcn.gather.tool.wave.pojo.dto.WaveDataDTO;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 本地调试 getComtrade 的命令行入口。
|
||||
*/
|
||||
public final class WaveFileComponentTestMain {
|
||||
|
||||
/** 默认测试 CFG 文件路径。 */
|
||||
private static final String DEFAULT_CFG_PATH = "D:\\00-B7-8D-00-E4-09\\PQMonitor_PQM2_006970_20260320_175033_734.CFG";
|
||||
/** 默认测试 DAT 文件路径。 */
|
||||
private static final String DEFAULT_DAT_PATH = "D:\\00-B7-8D-00-E4-09\\PQMonitor_PQM2_006970_20260320_175033_734.DAT";
|
||||
/** 默认解析类型,1 表示普通展示。 */
|
||||
private static final int DEFAULT_PARSE_TYPE = 1;
|
||||
/** 默认使用浮动门槛计算特征值。 */
|
||||
private static final boolean DEFAULT_DYNAMIC_THRESHOLD = true;
|
||||
|
||||
private WaveFileComponentTestMain() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 用法:
|
||||
* java com.njcn.gather.tool.wave.component.WaveFileComponentTestMain <cfgPath> <datPath> [parseType]
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length < 2) {
|
||||
System.out.println("未传入参数,使用默认测试文件路径");
|
||||
System.out.println("cfgPath: " + DEFAULT_CFG_PATH);
|
||||
System.out.println("datPath: " + DEFAULT_DAT_PATH);
|
||||
}
|
||||
|
||||
Path cfgPath = Paths.get(args.length > 0 ? args[0] : DEFAULT_CFG_PATH);
|
||||
Path datPath = Paths.get(args.length > 1 ? args[1] : DEFAULT_DAT_PATH);
|
||||
int parseType = args.length > 2 ? Integer.parseInt(args[2]) : DEFAULT_PARSE_TYPE;
|
||||
|
||||
WaveFileComponent waveFileComponent = new WaveFileComponent();
|
||||
try (InputStream cfgStream = Files.newInputStream(cfgPath);
|
||||
InputStream datStream = Files.newInputStream(datPath)) {
|
||||
WaveDataDTO waveDataDTO = waveFileComponent.getComtrade(cfgStream, datStream, parseType);
|
||||
printComtradeResult(waveDataDTO);
|
||||
|
||||
WaveDataDTO validWaveDataDTO = waveFileComponent.getValidData(waveDataDTO);
|
||||
printValidDataResult(validWaveDataDTO);
|
||||
|
||||
List<EigenvalueDTO> eigenvalues = waveFileComponent.getEigenvalue(validWaveDataDTO, DEFAULT_DYNAMIC_THRESHOLD);
|
||||
printEigenvalueResult(eigenvalues);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印 getComtrade 的关键摘要,便于快速人工核对。
|
||||
*/
|
||||
private static void printComtradeResult(WaveDataDTO waveDataDTO) {
|
||||
System.out.println("=== getComtrade 结果 ===");
|
||||
System.out.println("事件时间: " + waveDataDTO.getTime());
|
||||
System.out.println("相别数: " + waveDataDTO.getIPhasic());
|
||||
System.out.println("标题数: " + sizeOf(waveDataDTO.getWaveTitle()));
|
||||
System.out.println("通道数: " + sizeOf(waveDataDTO.getChannelNames()));
|
||||
System.out.println("波形点数: " + sizeOf(waveDataDTO.getListWaveData()));
|
||||
if (waveDataDTO.getComtradeCfgDTO() != null) {
|
||||
System.out.println("模拟量通道数: " + waveDataDTO.getComtradeCfgDTO().getNAnalogNum());
|
||||
System.out.println("开关量通道数: " + waveDataDTO.getComtradeCfgDTO().getNDigitalNum());
|
||||
System.out.println("最终采样率: " + waveDataDTO.getComtradeCfgDTO().getFinalSampleRate());
|
||||
}
|
||||
if (waveDataDTO.getWaveTitle() != null && !waveDataDTO.getWaveTitle().isEmpty()) {
|
||||
System.out.println("波形标题: " + waveDataDTO.getWaveTitle());
|
||||
}
|
||||
if (waveDataDTO.getListWaveData() != null && !waveDataDTO.getListWaveData().isEmpty()) {
|
||||
System.out.println("首行数据: " + waveDataDTO.getListWaveData().get(0));
|
||||
System.out.println("末行数据: " + waveDataDTO.getListWaveData().get(waveDataDTO.getListWaveData().size() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印 getValidData 的关键摘要。
|
||||
*/
|
||||
private static void printValidDataResult(WaveDataDTO waveDataDTO) {
|
||||
System.out.println("=== getValidData 结果 ===");
|
||||
System.out.println("RMS 点数: " + sizeOf(waveDataDTO.getListRmsData()));
|
||||
System.out.println("RMS 最小值点数: " + sizeOf(waveDataDTO.getListRmsMinData()));
|
||||
if (waveDataDTO.getListRmsData() != null && !waveDataDTO.getListRmsData().isEmpty()) {
|
||||
System.out.println("RMS 首行数据: " + waveDataDTO.getListRmsData().get(0));
|
||||
System.out.println("RMS 末行数据: " + waveDataDTO.getListRmsData().get(waveDataDTO.getListRmsData().size() - 1));
|
||||
}
|
||||
if (waveDataDTO.getListRmsMinData() != null && !waveDataDTO.getListRmsMinData().isEmpty()) {
|
||||
System.out.println("RMS 最小值数据: " + waveDataDTO.getListRmsMinData());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印特征值结果摘要。
|
||||
*/
|
||||
private static void printEigenvalueResult(List<EigenvalueDTO> eigenvalues) {
|
||||
System.out.println("=== getEigenvalue 结果 ===");
|
||||
System.out.println("特征值数量: " + sizeOf(eigenvalues));
|
||||
if (eigenvalues == null || eigenvalues.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < eigenvalues.size(); i++) {
|
||||
EigenvalueDTO eigenvalueDTO = eigenvalues.get(i);
|
||||
System.out.println("第" + (i + 1) + "相: amplitude=" + eigenvalueDTO.getAmplitude()
|
||||
+ ", residualVoltage=" + eigenvalueDTO.getResidualVoltage()
|
||||
+ ", ratedVoltage=" + eigenvalueDTO.getRatedVoltage()
|
||||
+ ", durationTime=" + eigenvalueDTO.getDurationTime());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全返回列表大小,避免空指针。
|
||||
*/
|
||||
private static int sizeOf(List<?> list) {
|
||||
return list == null ? 0 : list.size();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.njcn.gather.tool.wave.pojo.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 瞬时波形数据。
|
||||
*/
|
||||
@Data
|
||||
public class InstantData {
|
||||
|
||||
/** 当前曲线最大值。 */
|
||||
private Float max;
|
||||
|
||||
/** 当前曲线最小值。 */
|
||||
private Float min;
|
||||
|
||||
/** A 相点位。 */
|
||||
private List<List<Float>> aValue = new ArrayList<>();
|
||||
|
||||
/** B 相点位。 */
|
||||
private List<List<Float>> bValue = new ArrayList<>();
|
||||
|
||||
/** C 相点位。 */
|
||||
private List<List<Float>> cValue = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.njcn.gather.tool.wave.pojo.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* RMS 波形数据。
|
||||
*/
|
||||
@Data
|
||||
public class RmsData {
|
||||
|
||||
/** 当前曲线最大值。 */
|
||||
private Float max;
|
||||
|
||||
/** 当前曲线最小值。 */
|
||||
private Float min;
|
||||
|
||||
/** A 相点位。 */
|
||||
private List<List<Float>> aValue = new ArrayList<>();
|
||||
|
||||
/** B 相点位。 */
|
||||
private List<List<Float>> bValue = new ArrayList<>();
|
||||
|
||||
/** C 相点位。 */
|
||||
private List<List<Float>> cValue = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.njcn.gather.tool.wave.pojo.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 前端查看使用的波形明细。
|
||||
*/
|
||||
@Data
|
||||
public class WaveDataDetail {
|
||||
|
||||
/** 瞬时波形数据。 */
|
||||
private InstantData instantData;
|
||||
|
||||
/** RMS 波形数据。 */
|
||||
private RmsData rmsData;
|
||||
|
||||
/** A 相名称。 */
|
||||
private String a = "A相";
|
||||
|
||||
/** B 相名称。 */
|
||||
private String b = "B相";
|
||||
|
||||
/** C 相名称。 */
|
||||
private String c = "C相";
|
||||
|
||||
/** 通道名称。 */
|
||||
private String channelName;
|
||||
|
||||
/** 单位。 */
|
||||
private String unit;
|
||||
|
||||
/** 是否为开口三角模式。 */
|
||||
private Boolean isOpen = false;
|
||||
|
||||
/** 当前图标题。 */
|
||||
private String title;
|
||||
|
||||
/** 线条颜色。 */
|
||||
private List<String> colors = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.njcn.gather.tool.wave.pojo.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 模拟量通道信息。
|
||||
*/
|
||||
@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;
|
||||
/** 值类型,P 表示一次值,S 表示二次值。 */
|
||||
private String szValueType;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.njcn.gather.tool.wave.pojo.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* COMTRADE CFG 配置数据。
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ComtradeCfgDTO implements Serializable {
|
||||
|
||||
/** 通道总数。 */
|
||||
private Integer nChannelNum;
|
||||
/** 相别数量。 */
|
||||
private Integer nPhasic;
|
||||
/** 模拟量通道数。 */
|
||||
private Integer nAnalogNum;
|
||||
/** 开关量通道数。 */
|
||||
private Integer nDigitalNum;
|
||||
/** 录波开始时间。 */
|
||||
private Date timeStart;
|
||||
/** 触发时间。 */
|
||||
private Date timeTrige;
|
||||
/** 模拟量通道配置。 */
|
||||
private List<AnalogDTO> lstAnalogDTO;
|
||||
/** 开关量通道配置。 */
|
||||
private List<DigitalDTO> lstDigitalDTO;
|
||||
/** 采样率分段数。 */
|
||||
public Integer nRates;
|
||||
/** 采样率分段配置。 */
|
||||
public List<RateDTO> lstRate;
|
||||
/** 首个触发时间对象。 */
|
||||
private Date firstTime;
|
||||
/** 首个触发毫秒值。 */
|
||||
private Integer firstMs;
|
||||
/** 触发前推点数。 */
|
||||
private Integer nPush = 0;
|
||||
/** 最终采样率。 */
|
||||
private Integer finalSampleRate;
|
||||
/** 总周波数。 */
|
||||
private Integer nAllWaveNum = 0;
|
||||
/** 文件编码类型,例如 BINARY。 */
|
||||
private String strBinType;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.njcn.gather.tool.wave.pojo.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 开关量通道信息。
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DigitalDTO implements Serializable {
|
||||
|
||||
/** 通道序号。 */
|
||||
private Integer nIndex;
|
||||
/** 通道名称。 */
|
||||
private String szChannleName;
|
||||
/** 相位名称。 */
|
||||
private String szPhasicName;
|
||||
/** 监视通道名称。 */
|
||||
private String szMonitoredChannleName;
|
||||
/** 初始值。 */
|
||||
private Integer Initial;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.njcn.gather.tool.wave.pojo.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 波形特征值结果。
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class EigenvalueDTO implements Serializable {
|
||||
|
||||
/** 特征幅值百分比。 */
|
||||
private float amplitude;
|
||||
/** 残余电压。 */
|
||||
private float residualVoltage;
|
||||
/** 额定电压。 */
|
||||
private float ratedVoltage;
|
||||
/** 持续时间。 */
|
||||
private float durationTime;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.njcn.gather.tool.wave.pojo.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 突变量计算结果。
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MutationDTO implements Serializable {
|
||||
|
||||
/** 离线 RMS 数据。 */
|
||||
private List<List<Float>> listRms_Offline = new ArrayList<>();
|
||||
/** 离线突变量数据。 */
|
||||
private List<List<Float>> listTBL_Offline = new ArrayList<>();
|
||||
/** A 相最小幅值。 */
|
||||
private double fMinMagA = 99999d;
|
||||
/** B 相最小幅值。 */
|
||||
private double fMinMagB = 99999d;
|
||||
/** C 相最小幅值。 */
|
||||
private double fMinMagC = 99999d;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.njcn.gather.tool.wave.pojo.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 采样率分段配置。
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RateDTO implements Serializable {
|
||||
|
||||
/** 单周波采样点数。 */
|
||||
private Integer nOneSample;
|
||||
/** 当前分段总采样点数。 */
|
||||
private Integer nSampleNum;
|
||||
/** 是否为需要补点的 RMS 数据。 */
|
||||
public Boolean bRMSFlag;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.njcn.gather.tool.wave.pojo.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 波形解析结果数据。
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class WaveDataDTO implements Serializable {
|
||||
|
||||
/** CFG 配置数据。 */
|
||||
private ComtradeCfgDTO comtradeCfgDTO;
|
||||
/** 波形标题。 */
|
||||
private List<String> waveTitle;
|
||||
/** 通道名称列表。 */
|
||||
private List<String> channelNames;
|
||||
/** 原始波形数据。 */
|
||||
private List<List<Float>> listWaveData;
|
||||
/** RMS 波形数据。 */
|
||||
private List<List<Float>> listRmsData;
|
||||
/** RMS 最小值数据。 */
|
||||
private List<List<Float>> listRmsMinData;
|
||||
/** 相别数量。 */
|
||||
private Integer iPhasic;
|
||||
/** PT 接线方式,0 星形,1 三角,2 开口三角。 */
|
||||
private Integer ptType;
|
||||
/** PT 变比。 */
|
||||
private Double pt;
|
||||
/** CT 变比。 */
|
||||
private Double ct;
|
||||
/** 事件发生时刻。 */
|
||||
private String time;
|
||||
/** 测点名称。 */
|
||||
private String monitorName;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.njcn.gather.tool.wave.pojo.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 波形处理相关响应码定义。
|
||||
*/
|
||||
@Getter
|
||||
public enum WaveFileResponseEnum {
|
||||
|
||||
/** 暂降事件或监测点不存在。 */
|
||||
EVENT_NOT_FOUND("A00651", "暂降事件或监测点不存在"),
|
||||
/** 波形文件不存在。 */
|
||||
ANALYSE_WAVE_NOT_FOUND("A00652", "波形文件不存在"),
|
||||
/** CFG 文件解析失败。 */
|
||||
CFG_DATA_ERROR("A00653", "CFG 文件解析失败"),
|
||||
/** DAT 文件读取失败。 */
|
||||
DAT_DATA_ERROR("A00654", "DAT 文件读取失败"),
|
||||
/** RMS 数据计算失败。 */
|
||||
RMS_DATA_ERROR("A00655", "RMS 数据计算失败"),
|
||||
/** 波形文件数据缺失。 */
|
||||
WAVE_DATA_INVALID("A00656", "波形文件数据缺失"),
|
||||
/** 波形图片合成失败。 */
|
||||
COMPOSE_PIC_ERROR("A00657", "波形图片合成失败");
|
||||
|
||||
/** 响应码。 */
|
||||
private final String code;
|
||||
|
||||
/** 响应消息。 */
|
||||
private final String message;
|
||||
|
||||
WaveFileResponseEnum(String code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.njcn.gather.tool.wave.pojo.param;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* COMTRADE 波形解析参数。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("COMTRADE 波形解析参数")
|
||||
public class WaveComtradeParseParam {
|
||||
|
||||
/** 解析类型。 */
|
||||
@ApiModelProperty(value = "解析类型:0 高级算法采样率 32-128,1 普通展示,2 App 抽点,3 原始波形", example = "1")
|
||||
private Integer parseType = 1;
|
||||
|
||||
/** PT 接线方式。 */
|
||||
@ApiModelProperty(value = "PT 接线方式:0 星形,1 三角,2 开口三角", example = "0")
|
||||
private Integer ptType = 0;
|
||||
|
||||
/** PT 变比。 */
|
||||
@ApiModelProperty(value = "PT 变比,默认 1")
|
||||
private Double pt = 1D;
|
||||
|
||||
/** CT 变比。 */
|
||||
@ApiModelProperty(value = "CT 变比,默认 1")
|
||||
private Double ct = 1D;
|
||||
|
||||
/** 测点名称。 */
|
||||
@ApiModelProperty(value = "测点名称")
|
||||
private String monitorName = "未命名测点";
|
||||
|
||||
/** 是否计算 RMS。 */
|
||||
@ApiModelProperty(value = "是否计算 RMS,默认 true")
|
||||
private Boolean calculateRms = true;
|
||||
|
||||
/** 是否构建查看明细。 */
|
||||
@ApiModelProperty(value = "是否组装前端查看明细,默认 true")
|
||||
private Boolean buildDetails = true;
|
||||
|
||||
/** 是否计算特征值。 */
|
||||
@ApiModelProperty(value = "是否计算特征值,默认 false")
|
||||
private Boolean calculateEigenvalue = false;
|
||||
|
||||
/** 是否使用浮动门槛。 */
|
||||
@ApiModelProperty(value = "特征值计算方式,true 浮动门槛,false 固定门槛,默认 true")
|
||||
private Boolean dynamicThreshold = true;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.njcn.gather.tool.wave.pojo.param;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 文本波形解析参数。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("波形解析参数")
|
||||
public class WaveParseParam {
|
||||
|
||||
/** 波形文本内容。 */
|
||||
@ApiModelProperty(value = "波形文本内容,支持单列幅值、单行多值或双列时间/幅值数据", required = true)
|
||||
private String waveformText;
|
||||
|
||||
/** 分隔符。 */
|
||||
@ApiModelProperty(value = "分隔符,默认 AUTO 自动识别,也支持 TAB、SPACE 或直接传入具体字符")
|
||||
private String separator;
|
||||
|
||||
/** 是否显式包含 X 轴列。 */
|
||||
@ApiModelProperty(value = "是否包含 X 轴列,true 表示文本中显式传入时间列")
|
||||
private Boolean containsXAxis;
|
||||
|
||||
/** X 轴列下标。 */
|
||||
@ApiModelProperty(value = "X 轴列下标,默认 0")
|
||||
private Integer xColumnIndex;
|
||||
|
||||
/** Y 轴列下标。 */
|
||||
@ApiModelProperty(value = "Y 轴列下标,单列波形默认 0,双列波形默认 1")
|
||||
private Integer yColumnIndex;
|
||||
|
||||
/** 跳过的表头行数。 */
|
||||
@ApiModelProperty(value = "跳过的表头行数,默认 0")
|
||||
private Integer skipHeaderLines;
|
||||
|
||||
/** 单列波形采样间隔。 */
|
||||
@ApiModelProperty(value = "单列波形的采样间隔,默认 1")
|
||||
private BigDecimal samplingInterval;
|
||||
|
||||
/** 最大返回点数。 */
|
||||
@ApiModelProperty(value = "返回的最大点位数,超过时自动下采样,默认 2000")
|
||||
private Integer maxPointCount;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.njcn.gather.tool.wave.pojo.vo;
|
||||
|
||||
import com.njcn.gather.tool.wave.pojo.bo.WaveDataDetail;
|
||||
import com.njcn.gather.tool.wave.pojo.dto.EigenvalueDTO;
|
||||
import com.njcn.gather.tool.wave.pojo.dto.WaveDataDTO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* COMTRADE 波形解析结果。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("COMTRADE 波形解析结果")
|
||||
public class WaveComtradeResultVO {
|
||||
|
||||
/** 波形基础数据。 */
|
||||
@ApiModelProperty("波形基础数据")
|
||||
private WaveDataDTO waveData;
|
||||
|
||||
/** 前端查看明细。 */
|
||||
@ApiModelProperty("前端查看明细")
|
||||
private List<WaveDataDetail> waveDataDetails;
|
||||
|
||||
/** 特征值结果。 */
|
||||
@ApiModelProperty("特征值结果")
|
||||
private List<EigenvalueDTO> eigenvalues;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.njcn.gather.tool.wave.pojo.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 波形解析结果。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("波形解析结果")
|
||||
public class WaveParseResultVO {
|
||||
|
||||
/** 是否包含显式 X 轴。 */
|
||||
@ApiModelProperty("是否包含显式 X 轴")
|
||||
private Boolean containsXAxis;
|
||||
|
||||
/** 原始有效点位数。 */
|
||||
@ApiModelProperty("原始有效点位数")
|
||||
private Integer sourcePointCount;
|
||||
|
||||
/** 返回的显示点位数。 */
|
||||
@ApiModelProperty("返回的显示点位数")
|
||||
private Integer displayPointCount;
|
||||
|
||||
/** 被忽略的无效行数。 */
|
||||
@ApiModelProperty("被忽略的无效行数")
|
||||
private Integer ignoredLineCount;
|
||||
|
||||
/** 是否发生下采样。 */
|
||||
@ApiModelProperty("是否发生下采样")
|
||||
private Boolean sampled;
|
||||
|
||||
/** X 轴最小值。 */
|
||||
@ApiModelProperty("X 轴最小值")
|
||||
private BigDecimal minX;
|
||||
|
||||
/** X 轴最大值。 */
|
||||
@ApiModelProperty("X 轴最大值")
|
||||
private BigDecimal maxX;
|
||||
|
||||
/** Y 轴最小值。 */
|
||||
@ApiModelProperty("Y 轴最小值")
|
||||
private BigDecimal minY;
|
||||
|
||||
/** Y 轴最大值。 */
|
||||
@ApiModelProperty("Y 轴最大值")
|
||||
private BigDecimal maxY;
|
||||
|
||||
/** Y 轴平均值。 */
|
||||
@ApiModelProperty("Y 轴平均值")
|
||||
private BigDecimal averageY;
|
||||
|
||||
/** 用于查看的波形点位。 */
|
||||
@ApiModelProperty("用于查看的波形点位")
|
||||
private List<WavePointVO> points;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.njcn.gather.tool.wave.pojo.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 波形点位。
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@ApiModel("波形点位")
|
||||
public class WavePointVO {
|
||||
|
||||
/** X 轴值。 */
|
||||
@ApiModelProperty("X 轴值")
|
||||
private BigDecimal x;
|
||||
|
||||
/** Y 轴值。 */
|
||||
@ApiModelProperty("Y 轴值")
|
||||
private BigDecimal y;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.njcn.gather.tool.wave.utils;
|
||||
|
||||
/**
|
||||
* 波形二进制数据转换工具。
|
||||
*/
|
||||
public final class BitConverter {
|
||||
|
||||
private BitConverter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将两个字节转换为无符号 short。
|
||||
*
|
||||
* @param bytes 字节数组
|
||||
* @param off 起始位置
|
||||
* @return 转换结果
|
||||
*/
|
||||
public static short byte2ToUnsignedShort(byte[] bytes, int off) {
|
||||
int low = bytes[off] & 0xFF;
|
||||
int high = bytes[off + 1] & 0xFF;
|
||||
return (short) (((high & 0x00FF) << 8) | (0x00FF & low));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将四个字节转换为 float。
|
||||
*
|
||||
* @param bytes 字节数组
|
||||
* @param index 起始位置
|
||||
* @return 转换结果
|
||||
*/
|
||||
public static float byte4float(byte[] bytes, int index) {
|
||||
int value = bytes[index] & 0xFF;
|
||||
value |= ((long) bytes[index + 1] << 8);
|
||||
value &= 0xFFFF;
|
||||
value |= ((long) bytes[index + 2] << 16);
|
||||
value &= 0xFFFFFF;
|
||||
value |= ((long) bytes[index + 3] << 24);
|
||||
return Float.intBitsToFloat(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将四个字节转换为 int32。
|
||||
*
|
||||
* @param bytes 字节数组
|
||||
* @param off 起始位置
|
||||
* @return 转换结果
|
||||
*/
|
||||
public static int byte4ToInt(byte[] bytes, int off) {
|
||||
int b0 = bytes[off] & 0xFF;
|
||||
int b1 = bytes[off + 1] & 0xFF;
|
||||
int b2 = bytes[off + 2] & 0xFF;
|
||||
int b3 = bytes[off + 3] & 0xFF;
|
||||
return (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将两个字节转换为 int16。
|
||||
*
|
||||
* @param bytes 字节数组
|
||||
* @param off 起始位置
|
||||
* @return 转换结果
|
||||
*/
|
||||
public static int byte2ToInt(byte[] bytes, int off) {
|
||||
int b0 = bytes[off] & 0xFF;
|
||||
int b1 = bytes[off + 1] & 0xFF;
|
||||
return (b1 << 8) | b0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将四个字节转换为 long。
|
||||
*
|
||||
* @param bytes 字节数组
|
||||
* @param off 起始位置
|
||||
* @return 转换结果
|
||||
*/
|
||||
public static long byte4ToLong(byte[] bytes, int off) {
|
||||
long b0 = bytes[off] & 0xFF;
|
||||
long b1 = bytes[off + 1] & 0xFF;
|
||||
long b2 = bytes[off + 2] & 0xFF;
|
||||
long b3 = bytes[off + 3] & 0xFF;
|
||||
return (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
package com.njcn.gather.tool.wave.utils;
|
||||
|
||||
import com.njcn.gather.tool.wave.pojo.bo.InstantData;
|
||||
import com.njcn.gather.tool.wave.pojo.bo.RmsData;
|
||||
import com.njcn.gather.tool.wave.pojo.bo.WaveDataDetail;
|
||||
import com.njcn.gather.tool.wave.pojo.dto.WaveDataDTO;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 波形明细组装工具。
|
||||
*/
|
||||
public final class WaveUtil {
|
||||
|
||||
/** 单相展示颜色。 */
|
||||
private static final List<String> ONE_PHASE_COLORS = Collections.unmodifiableList(Arrays.asList("#DAA520", "#fff", "#fff"));
|
||||
/** 两相展示颜色。 */
|
||||
private static final List<String> TWO_PHASE_COLORS = Collections.unmodifiableList(Arrays.asList("#DAA520", "#2E8B57", "#fff"));
|
||||
/** 三相展示颜色。 */
|
||||
private static final List<String> THREE_PHASE_COLORS = Collections.unmodifiableList(Arrays.asList("#DAA520", "#2E8B57", "#A52a2a"));
|
||||
|
||||
private WaveUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将原始波形结果整理成前端查看明细。
|
||||
*
|
||||
* @param waveDataDTO 波形结果数据
|
||||
* @return 波形明细列表
|
||||
*/
|
||||
public static List<WaveDataDetail> filterWaveData(WaveDataDTO waveDataDTO) {
|
||||
List<WaveDataDetail> waveDataDetails = new ArrayList<>();
|
||||
List<String> waveTitle = waveDataDTO.getWaveTitle();
|
||||
List<String> channelNames = waveDataDTO.getChannelNames();
|
||||
int phaseCount = waveDataDTO.getIPhasic();
|
||||
boolean openTri = waveDataDTO.getPtType() != null && waveDataDTO.getPtType() == 2;
|
||||
int picCount = (waveTitle.size() - 1) / phaseCount;
|
||||
|
||||
for (int i = 0; i < picCount; i++) {
|
||||
WaveDataDetail detail = buildBaseDetail(waveTitle, channelNames, phaseCount, i);
|
||||
float ratio = resolveRatio(waveDataDTO, waveTitle.get(phaseCount * i + 1), detail);
|
||||
|
||||
detail.setInstantData(buildInstantData(waveDataDTO.getListWaveData(), waveTitle, phaseCount, i, ratio, openTri));
|
||||
detail.setRmsData(buildRmsData(waveDataDTO.getListRmsData(), waveTitle, phaseCount, i, ratio, openTri));
|
||||
detail.setIsOpen(openTri);
|
||||
waveDataDetails.add(detail);
|
||||
}
|
||||
return waveDataDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建单组波形的基础明细信息。
|
||||
*/
|
||||
private static WaveDataDetail buildBaseDetail(List<String> waveTitle, List<String> channelNames, int phaseCount, int index) {
|
||||
WaveDataDetail detail = new WaveDataDetail();
|
||||
switch (phaseCount) {
|
||||
case 1:
|
||||
detail.setA(waveTitle.get(index + 1).substring(1));
|
||||
detail.setB("");
|
||||
detail.setC("");
|
||||
detail.setChannelName(channelNames.get(index + 1));
|
||||
detail.setColors(new ArrayList<>(ONE_PHASE_COLORS));
|
||||
break;
|
||||
case 2:
|
||||
detail.setA(waveTitle.get(index * 2 + 1).substring(1));
|
||||
detail.setB(waveTitle.get(index * 2 + 2).substring(1));
|
||||
detail.setC("");
|
||||
detail.setChannelName(channelNames.get(index * 2 + 1));
|
||||
detail.setColors(new ArrayList<>(TWO_PHASE_COLORS));
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
detail.setA(waveTitle.get(index * 3 + 1).substring(1));
|
||||
detail.setB(waveTitle.get(index * 3 + 2).substring(1));
|
||||
detail.setC(waveTitle.get(index * 3 + 3).substring(1));
|
||||
detail.setChannelName(channelNames.get(index * 3 + 1));
|
||||
detail.setColors(new ArrayList<>(THREE_PHASE_COLORS));
|
||||
break;
|
||||
}
|
||||
return detail;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据标题判断比例和单位。
|
||||
*/
|
||||
private static float resolveRatio(WaveDataDTO waveDataDTO, String title, WaveDataDetail detail) {
|
||||
if (title.substring(0, 1).equalsIgnoreCase("U")) {
|
||||
detail.setUnit("kV");
|
||||
return waveDataDTO.getPt().floatValue() / 1000;
|
||||
}
|
||||
detail.setUnit("A");
|
||||
return waveDataDTO.getCt().floatValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 RMS 明细数据。
|
||||
*/
|
||||
private static RmsData buildRmsData(List<List<Float>> sourceData, List<String> waveTitle, int phaseCount, int index,
|
||||
float ratio, boolean openTri) {
|
||||
List<List<Float>> aValues = new ArrayList<>();
|
||||
List<List<Float>> bValues = new ArrayList<>();
|
||||
List<List<Float>> cValues = new ArrayList<>();
|
||||
float max = Float.NEGATIVE_INFINITY;
|
||||
float min = Float.POSITIVE_INFINITY;
|
||||
|
||||
if (sourceData == null) {
|
||||
sourceData = Collections.emptyList();
|
||||
}
|
||||
|
||||
for (List<Float> row : sourceData) {
|
||||
if (row == null || row.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
float x = row.get(0);
|
||||
float valueA = 0f;
|
||||
float valueB = 0f;
|
||||
float valueC = 0f;
|
||||
boolean existsA = false;
|
||||
boolean existsB = false;
|
||||
boolean existsC = false;
|
||||
|
||||
for (int m = 0; m < phaseCount; m++) {
|
||||
String currentTitle = waveTitle.get(phaseCount * index + m + 1).substring(1);
|
||||
float value = row.get(phaseCount * index + m + 1) * ratio;
|
||||
if (currentTitle.contains("A")) {
|
||||
valueA = value;
|
||||
existsA = true;
|
||||
aValues.add(buildPoint(x, value));
|
||||
} else if (currentTitle.contains("B")) {
|
||||
valueB = value;
|
||||
existsB = true;
|
||||
bValues.add(buildPoint(x, value));
|
||||
} else if (currentTitle.contains("C")) {
|
||||
valueC = value;
|
||||
existsC = true;
|
||||
cValues.add(buildPoint(x, value));
|
||||
}
|
||||
}
|
||||
|
||||
if (existsA) {
|
||||
max = Math.max(max, valueA);
|
||||
min = Math.min(min, valueA);
|
||||
}
|
||||
if (existsB) {
|
||||
max = Math.max(max, valueB);
|
||||
if (!openTri) {
|
||||
min = Math.min(min, valueB);
|
||||
}
|
||||
}
|
||||
if (existsC) {
|
||||
max = Math.max(max, valueC);
|
||||
min = Math.min(min, valueC);
|
||||
}
|
||||
}
|
||||
|
||||
RmsData data = new RmsData();
|
||||
data.setAValue(aValues);
|
||||
data.setBValue(bValues);
|
||||
data.setCValue(cValues);
|
||||
data.setMax(max == Float.NEGATIVE_INFINITY ? 0f : max);
|
||||
data.setMin(min == Float.POSITIVE_INFINITY ? 0f : min);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建单个点位。
|
||||
*/
|
||||
private static List<Float> buildPoint(float x, float y) {
|
||||
List<Float> point = new ArrayList<>(2);
|
||||
point.add(x);
|
||||
point.add(y);
|
||||
return point;
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于瞬时数据构建明细对象。
|
||||
*/
|
||||
private static InstantData buildInstantData(List<List<Float>> sourceData, List<String> waveTitle, int phaseCount, int index,
|
||||
float ratio, boolean openTri) {
|
||||
RmsData rmsData = buildRmsData(sourceData, waveTitle, phaseCount, index, ratio, openTri);
|
||||
InstantData instantData = new InstantData();
|
||||
instantData.setAValue(rmsData.getAValue());
|
||||
instantData.setBValue(rmsData.getBValue());
|
||||
instantData.setCValue(rmsData.getCValue());
|
||||
instantData.setMax(rmsData.getMax());
|
||||
instantData.setMin(rmsData.getMin());
|
||||
return instantData;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user