From b607189bd3780d499a27e626ff7a617906e4f7e1 Mon Sep 17 00:00:00 2001 From: hzj <826100833@qq.com> Date: Mon, 27 Apr 2026 16:17:22 +0800 Subject: [PATCH] =?UTF-8?q?=E9=AB=98=E7=BA=A7=E7=AE=97=E6=B3=95=E5=92=8C?= =?UTF-8?q?=E6=9A=82=E6=80=81=E6=96=87=E4=BB=B6=E5=90=8C=E6=AD=A5=E5=90=88?= =?UTF-8?q?=E5=B9=B6jar=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- influx-data/influx-source/pom.xml | 24 +- .../influx/bo/po/OracleRmpEventDetailPO.java | 3 + .../com/njcn/influx/bo/po/PqsEventLog.java | 44 + .../njcn/influx/component/BitConverter.java | 84 + .../influx/component/WaveFileComponent.java | 1742 +++++++++++++++++ .../njcn/influx/component/dto/AnalogDTO.java | 46 + .../influx/component/dto/ComtradeCfgDTO.java | 54 + .../njcn/influx/component/dto/DigitalDTO.java | 30 + .../influx/component/dto/EigenvalueDTO.java | 28 + .../influx/component/dto/MutationDTO.java | 27 + .../njcn/influx/component/dto/RateDTO.java | 27 + .../influx/component/dto/WaveDataDTO.java | 46 + .../com/njcn/influx/config/OtherConfig.java | 20 + .../com/njcn/influx/config/TargetConfig.java | 36 + .../njcn/influx/config/ThreadPoolConfig.java | 41 + .../event/cause/algorithm/DQTransform.java | 202 ++ .../event/cause/algorithm/FFTUtils.java | 124 ++ .../event/cause/algorithm/MathUtils.java | 210 ++ .../event/cause/algorithm/SVDUtils.java | 138 ++ .../event/cause/core/FeatureCalculator.java | 427 ++++ .../event/cause/core/ThresholdJudge.java | 161 ++ .../event/cause/core/VoltageSagAnalyzer.java | 284 +++ .../influx/event/cause/io/ComtradeReader.java | 166 ++ .../influx/event/cause/jna/QvvrCauseDLL.java | 134 ++ .../event/cause/model/AnalysisResult.java | 148 ++ .../influx/event/cause/model/Complex.java | 88 + .../influx/event/cause/model/DataCause.java | 163 ++ .../influx/event/cause/model/DataFeature.java | 163 ++ .../event/cause/model/EventAnalysisDTO.java | 82 + .../event/cause/model/QvvrDataStruct.java | 102 + .../influx/event/cause/model/VecStruct.java | 51 + .../njcn/influx/event/type/jna/QvvrDLL.java | 190 ++ .../mapper/OracleRmpEventDetailPOMapper.java | 4 + .../njcn/influx/mapper/PqDeviceMapper.java | 3 + .../njcn/influx/mapper/PqsEventLogMapper.java | 16 + .../mapping/OracleRmpEventDetailPOMapper.xml | 18 + .../influx/mapper/mapping/PqDeviceMapper.xml | 15 + .../mapper/mapping/PqsEventLogMapper.xml | 19 + .../OracleEventDetailToMysqlService.java | 1 + .../influx/service/OracleToMysqlService.java | 16 + .../influx/service/PqsEventLogService.java | 17 + .../influx/service/RmpEventDetailService.java | 15 + .../service/impl/EventAsyncService.java | 244 +++ .../impl/OracleToMysqlServiceImpl.java | 147 ++ .../service/impl/PqsEventLogServiceImpl.java | 21 + .../impl/RmpEventDetailServiceImpl.java | 142 ++ .../java/com/njcn/influx/sftp/SftpClient.java | 126 ++ influx-data/influx-target/pom.xml | 31 + .../OracleToInfluxDBController.java | 20 +- .../njcn/influx/job/OracleToInfluxDBJob.java | 248 +-- .../com/njcn/influx/job/OracleToMySqlJob.java | 50 + .../src/main/resources/application-bd.yml | 130 ++ .../src/main/resources/application-hn.yml | 130 ++ .../src/main/resources/application.yml | 120 +- .../src/main/resources/application_hb.yml | 204 +- .../src/main/resources/application_sjzx.yml | 202 +- .../src/main/resources/libqvvr_balance_dll.so | Bin 0 -> 114976 bytes .../src/main/resources/libqvvr_cause_dll.so | Bin 0 -> 48232 bytes .../src/main/resources/libqvvr_dll.so | Bin 0 -> 207680 bytes .../src/main/resources/logback.xml | 142 ++ .../src/main/resources/qvvr_balance.dll | Bin 0 -> 220672 bytes .../src/main/resources/qvvr_cause_dll.dll | Bin 0 -> 47104 bytes .../src/main/resources/qvvr_dll.dll | Bin 0 -> 50176 bytes .../src/main/resources/static/index.html | 50 +- .../src/test/java/njcn/DataTest.java | 57 +- 65 files changed, 6781 insertions(+), 492 deletions(-) create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/bo/po/PqsEventLog.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/component/BitConverter.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/component/WaveFileComponent.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/AnalogDTO.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/ComtradeCfgDTO.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/DigitalDTO.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/EigenvalueDTO.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/MutationDTO.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/RateDTO.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/WaveDataDTO.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/config/OtherConfig.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/config/TargetConfig.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/config/ThreadPoolConfig.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/algorithm/DQTransform.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/algorithm/FFTUtils.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/algorithm/MathUtils.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/algorithm/SVDUtils.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/core/FeatureCalculator.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/core/ThresholdJudge.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/core/VoltageSagAnalyzer.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/io/ComtradeReader.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/jna/QvvrCauseDLL.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/AnalysisResult.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/Complex.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/DataCause.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/DataFeature.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/EventAnalysisDTO.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/QvvrDataStruct.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/VecStruct.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/event/type/jna/QvvrDLL.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/mapper/PqsEventLogMapper.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/mapper/mapping/PqDeviceMapper.xml create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/mapper/mapping/PqsEventLogMapper.xml create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/service/OracleToMysqlService.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/service/PqsEventLogService.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/service/RmpEventDetailService.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/service/impl/EventAsyncService.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/service/impl/OracleToMysqlServiceImpl.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/service/impl/PqsEventLogServiceImpl.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/service/impl/RmpEventDetailServiceImpl.java create mode 100644 influx-data/influx-source/src/main/java/com/njcn/influx/sftp/SftpClient.java create mode 100644 influx-data/influx-target/src/main/java/com/njcn/influx/job/OracleToMySqlJob.java create mode 100644 influx-data/influx-target/src/main/resources/application-bd.yml create mode 100644 influx-data/influx-target/src/main/resources/application-hn.yml create mode 100644 influx-data/influx-target/src/main/resources/libqvvr_balance_dll.so create mode 100644 influx-data/influx-target/src/main/resources/libqvvr_cause_dll.so create mode 100644 influx-data/influx-target/src/main/resources/libqvvr_dll.so create mode 100644 influx-data/influx-target/src/main/resources/logback.xml create mode 100644 influx-data/influx-target/src/main/resources/qvvr_balance.dll create mode 100644 influx-data/influx-target/src/main/resources/qvvr_cause_dll.dll create mode 100644 influx-data/influx-target/src/main/resources/qvvr_dll.dll diff --git a/influx-data/influx-source/pom.xml b/influx-data/influx-source/pom.xml index ca65b46..4b67a3e 100644 --- a/influx-data/influx-source/pom.xml +++ b/influx-data/influx-source/pom.xml @@ -22,7 +22,23 @@ org.projectlombok lombok - + + + org.ejml + ejml-simple + 0.41 + + + net.java.dev.jna + jna + 5.5.0 + + + + com.jcraft + jsch + 0.1.55 + cn.hutool hutool-all @@ -125,6 +141,12 @@ mysql mysql-connector-java + + org.apache.commons + commons-math3 + 3.6.1 + compile + diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/bo/po/OracleRmpEventDetailPO.java b/influx-data/influx-source/src/main/java/com/njcn/influx/bo/po/OracleRmpEventDetailPO.java index 1f6c763..debecdf 100644 --- a/influx-data/influx-source/src/main/java/com/njcn/influx/bo/po/OracleRmpEventDetailPO.java +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/bo/po/OracleRmpEventDetailPO.java @@ -168,4 +168,7 @@ public class OracleRmpEventDetailPO implements Serializable { @TableField(value = "TRANSIENTVALUE") private Double transientValue; + + @TableField(value = "CREATE_TIME") + private LocalDateTime createTime; } diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/bo/po/PqsEventLog.java b/influx-data/influx-source/src/main/java/com/njcn/influx/bo/po/PqsEventLog.java new file mode 100644 index 0000000..c6d874d --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/bo/po/PqsEventLog.java @@ -0,0 +1,44 @@ +package com.njcn.influx.bo.po; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.Date; + +/** + * Description: + * Date: 2026/04/20 上午 10:21【需求编号】 + * + * @author clam + * @version V1.0.0 + */ +@TableName(value = "PQS_EVENT_LOG") +@Data +public class PqsEventLog { + @TableId(value = "ID", type = IdType.INPUT) + private String id; + + @TableField(value = "EVENTDETAIL_INDEX") + private String eventdetailIndex; + + @TableField(value = "FILE_UP_FLAG") + private Integer fileupflag; + + @TableField(value = "DEAL_FLAG") + private Integer dealflag; + + @TableField(value = "CREAT_TIME") + private Date creattime; + + @TableField(value = "UPDATE_TIME") + private Date updatetime; + + @TableField(value = "REMARK") + private String remark; + + +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/component/BitConverter.java b/influx-data/influx-source/src/main/java/com/njcn/influx/component/BitConverter.java new file mode 100644 index 0000000..74eb5a9 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/component/BitConverter.java @@ -0,0 +1,84 @@ +package com.njcn.influx.component; + +public class BitConverter { + + /** + * byte数组转换为无符号short整数 + * @param bytes byte数组 + * @param off 开始位置 + * @return short整数 + */ + public static short byte2ToUnsignedShort(byte[] bytes, int off) { + if(off==1387308){ + System.out.println(1111); + } + int low = bytes[off]& 0xFF; + int high = bytes[off + 1]& 0xFF; + return (short)(((high & 0x00FF) << 8) | (0x00FF & low)); + } + + /** + * 字节转换为浮点 + * + * @param b 字节(至少4个字节) + * @param index 开始位置 + * @return + */ + public static float byte4float(byte[] b, int index) { + /* b=new byte[4]; + b[0]=-16; + b[1]=-1; + b[2]=117; + b[3]=66;*/ + + int l; + l = b[index + 0]; + l &= 0xff; + l |= ((long) b[index + 1] << 8); + l &= 0xffff; + l |= ((long) b[index + 2] << 16); + l &= 0xffffff; + l |= ((long) b[index + 3] << 24); + return Float.intBitsToFloat(l); + } + /** + * byte数组转换为int32整数 + * @param bytes byte数组 + * @param off 开始位置 + * @return int整数 + */ + 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; + } + + /** + * byte数组转换为int16整数 + * @param bytes byte数组 + * @param off 开始位置 + * @return int整数 + */ + public static int byte2ToInt(byte[] bytes, int off) { + int b0 = bytes[off] & 0xFF; + int b1 = bytes[off + 1] & 0xFF; + return (b1 << 8) | b0; + } + + /** + * byte数组转换为int16整数 + * @param bytes byte数组 + * @param off 开始位置 + * @return int整数 + */ + 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; + } +} diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/component/WaveFileComponent.java b/influx-data/influx-source/src/main/java/com/njcn/influx/component/WaveFileComponent.java new file mode 100644 index 0000000..da697fb --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/component/WaveFileComponent.java @@ -0,0 +1,1742 @@ +package com.njcn.influx.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.influx.component.BitConverter; +import com.njcn.influx.component.dto.*; +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) throws Exception { + WaveDataDTO waveDataDTO = new WaveDataDTO(); + // 首先判断文件路径是否为空 + // 读取cfg文件 + ComtradeCfgDTO comtradeCfgDTO = getComtradeCfg(cfgStream); + // 为空或者未找到结束符号 + if (comtradeCfgDTO == null || !"BINARY".equalsIgnoreCase(comtradeCfgDTO.getStrBinType())) { + throw new Exception("CFG文件解析有误"); + } + + /*****根据通道号计算相别** 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; + } + + public WaveDataDTO getComtradeNoAddPoints(InputStream cfgStream, InputStream datStream, int iType) throws Exception { + WaveDataDTO waveDataDTO = new WaveDataDTO(); + // 首先判断文件路径是否为空 + // 读取cfg文件 + ComtradeCfgDTO comtradeCfgDTO = getComtradeCfgNoAddPoints(cfgStream); + // 为空或者未找到结束符号 + if (comtradeCfgDTO == null || !"BINARY".equalsIgnoreCase(comtradeCfgDTO.getStrBinType())) { + throw new Exception("CFG文件解析有误"); + } + + /*****根据通道号计算相别** 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 = getComtradeDatNoAddPoints(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; + } + private ComtradeCfgDTO getComtradeCfgNoAddPoints(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; + } + + private List> getComtradeDatNoAddPoints(ComtradeCfgDTO comtradeCfgDTO, InputStream datStream, int iType) throws Exception { + //返回数据,如果仅仅做展示后期考虑换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 Exception("DAT文件数据读取失败"); + } + // 计算每个单独的数据块的大小 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++) { + if(nnInd>0){ + { + tmpRateDTO = comtradeCfgDTO.getLstRate().get(nIndex); + // 判断是否进入下一段 + if (i == tmpRateDTO.getNSampleNum() + nOffSet) { + nOffSet += tmpRateDTO.getNSampleNum(); + nIndex++; + if (nIndex == nnInd) { + break; + } + } + nWaveSpan = tmpRateDTO.getNOneSample() / newLstRate.get(nIndex).getNOneSample(); +// 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<>(); + 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 Exception("DAT文件数据读取失败"); + } + + return listWaveData; + } + + /********************************* + * 根据波形数据算出rms值数据 + * param waveDataDTO 瞬时波形(包含了CFG配置文件) + * List> 返回RMS波形 + **********************************/ + @SuppressWarnings("unused") + public WaveDataDTO getValidData(WaveDataDTO waveDataDTO) throws Exception { + //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 Exception("rms数据读取失败"); + } + } + 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) throws Exception { + //返回数据,如果仅仅做展示后期考虑换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 Exception("DAT文件数据读取失败"); + } + // 计算每个单独的数据块的大小 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(); + // C# 原实现中 bool 默认是 false,16~31 点/周波段也应按普通抽点处理 + tmpRateDTO.bRMSFlag = false; + // 有效值标志,如果是有效值,那么就需要反向补点,而不是抽点 + 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); + dfValue = (float) 20 / tmpRateDTO.getNOneSample(); + // C# 原实现中 RMS 段与普通抽点是两条独立控制流,不能挂在同一个取模条件下 + if (Boolean.TRUE.equals(newLstRate.get(nIndex).bRMSFlag)) { + //计算本段补点采样间隔 + nWaveSpan = newLstRate.get(nIndex).getNOneSample() / tmpRateDTO.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; + } + + // 计算本段抽点采样间隔 + nWaveSpan = tmpRateDTO.getNOneSample() / newLstRate.get(nIndex).getNOneSample(); + // 判断是否到了需要抽的采样点 + if (i % nWaveSpan == 0) { + // 计算每个通道的值 + //存储局部数据集合,包含了时间,A,B,C三相 + List 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(); + 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 Exception("DAT文件数据读取失败"); + } + + 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("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(); +// 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/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/AnalogDTO.java b/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/AnalogDTO.java new file mode 100644 index 0000000..49f2fae --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/AnalogDTO.java @@ -0,0 +1,46 @@ +package com.njcn.influx.component.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/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/ComtradeCfgDTO.java b/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/ComtradeCfgDTO.java new file mode 100644 index 0000000..cb5579b --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/ComtradeCfgDTO.java @@ -0,0 +1,54 @@ +package com.njcn.influx.component.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/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/DigitalDTO.java b/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/DigitalDTO.java new file mode 100644 index 0000000..a15a76b --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/DigitalDTO.java @@ -0,0 +1,30 @@ +package com.njcn.influx.component.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/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/EigenvalueDTO.java b/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/EigenvalueDTO.java new file mode 100644 index 0000000..ce366fc --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/EigenvalueDTO.java @@ -0,0 +1,28 @@ +package com.njcn.influx.component.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/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/MutationDTO.java b/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/MutationDTO.java new file mode 100644 index 0000000..3fb0faa --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/MutationDTO.java @@ -0,0 +1,27 @@ +package com.njcn.influx.component.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/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/RateDTO.java b/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/RateDTO.java new file mode 100644 index 0000000..238071e --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/RateDTO.java @@ -0,0 +1,27 @@ +package com.njcn.influx.component.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/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/WaveDataDTO.java b/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/WaveDataDTO.java new file mode 100644 index 0000000..c710e52 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/component/dto/WaveDataDTO.java @@ -0,0 +1,46 @@ +package com.njcn.influx.component.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/influx-data/influx-source/src/main/java/com/njcn/influx/config/OtherConfig.java b/influx-data/influx-source/src/main/java/com/njcn/influx/config/OtherConfig.java new file mode 100644 index 0000000..06c3f7f --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/config/OtherConfig.java @@ -0,0 +1,20 @@ +package com.njcn.influx.config; + +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; + +/** + * Description: + * Date: 2026/04/20 下午 1:27【需求编号】 + * + * @author clam + * @version V1.0.0 + */ +@Configuration +@Data +public class OtherConfig { + + @Value("${business.wavePath}") + private String wavePath; +} diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/config/TargetConfig.java b/influx-data/influx-source/src/main/java/com/njcn/influx/config/TargetConfig.java new file mode 100644 index 0000000..de866d8 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/config/TargetConfig.java @@ -0,0 +1,36 @@ +package com.njcn.influx.config; + +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; + +/** + * Description: + * Date: 2026/04/20 下午 2:47【需求编号】 + * + * @author clam + * @version V1.0.0 + */ +@Data +@Configuration +@Order(10) +public class TargetConfig { + @Value("${server.target.host}") + private String host; + @Value("${server.target.port}") + + private int port; + @Value("${server.target.username}") + + private String username; + @Value("${server.target.password}") + + private String password; + @Value("${server.target.privateKeyPath}") + + private String privateKeyPath; + @Value("${server.target.basePath}") + private String basePath; +} + diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/config/ThreadPoolConfig.java b/influx-data/influx-source/src/main/java/com/njcn/influx/config/ThreadPoolConfig.java new file mode 100644 index 0000000..a39e860 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/config/ThreadPoolConfig.java @@ -0,0 +1,41 @@ +package com.njcn.influx.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * Description: + * Date: 2026/04/20 下午 1:21【需求编号】 + * + * @author clam + * @version V1.0.0 + */ +@Configuration +@EnableAsync +public class ThreadPoolConfig { + + @Value("${task.pool.core-size:10}") + private int coreSize; + @Value("${task.pool.max-size:30}") + private int maxSize; + @Value("${task.pool.queue-capacity:1000}") + private int queueCapacity; + + @Bean("eventTaskExecutor") + public Executor eventTaskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(coreSize); + executor.setMaxPoolSize(maxSize); + executor.setQueueCapacity(queueCapacity); + executor.setThreadNamePrefix("event-task-"); + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + executor.initialize(); + return executor; + } +} diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/algorithm/DQTransform.java b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/algorithm/DQTransform.java new file mode 100644 index 0000000..009239f --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/algorithm/DQTransform.java @@ -0,0 +1,202 @@ +package com.njcn.influx.event.cause.algorithm; + + +import com.njcn.influx.event.cause.model.VecStruct; + +/** + * DQ变换算法实现 + * 对应C语言中的dq_delay.c文件 + */ +public class DQTransform { + private static final double PI = Math.PI; + + /** + * DQ变换延时处理 + * @param Va A相电压数组 + * @param t 时间数组 + * @param samplePoint 一个周期的采样点数 + * @param n 数据个数 + * @param f 频率 + * @param ua 输出幅值数组 + * @param angleUa 输出相角数组 + * @param vecU 输出相量数组 + */ + public static void dqDelay(float[] Va, float[] t, int samplePoint, int n, float f, + float[] ua, float[] angleUa, VecStruct[] vecU) { + + int delay = (int) (samplePoint / 6.0 + 0.5); // 延时量实际是超前60° + float ang = (float) delay / samplePoint; + + float[] upd1 = new float[n]; + float[] upq1 = new float[n]; + float[] upd = new float[n]; + float[] upq = new float[n]; + + // 延时计算dq变换 + for (int i = delay; i < n; i++) { + float Vo = Va[i - delay]; + float Vc = -(1.0f / 2.0f) * Va[i] + + (float) (Math.sqrt(3) / 2.0) * + (Va[i] * (float) Math.cos(ang * 2 * PI) - Vo) / + (float) Math.sin(ang * 2 * PI); + float Vb = -Va[i] - Vc; + + DQResult result = dqTransform(Va[i], Vb, Vc, t[i], f); + upd1[i] = result.upd; + upq1[i] = result.upq; + } + + // 延时段缺失值用第一个有效值填充 + for (int i = 0; i < delay; i++) { + upd1[i] = upd1[delay]; + upq1[i] = upq1[delay]; + } + + // 滤波处理 + int win = samplePoint / 4 + 1; + MathUtils.lowPassFilter(upd1, upd, n, win); + MathUtils.lowPassFilter(upq1, upq, n, win); + + // 计算最终结果 + for (int i = 0; i < n; i++) { + ua[i] = (float) (0.57735 * Math.sqrt(upd[i] * upd[i] + upq[i] * upq[i])); + angleUa[i] = (float) (Math.atan2(upq[i], upd[i]) / PI * 180); + + vecU[i] = new VecStruct(upd[i] * 0.57735f, upq[i] * 0.57735f); + } + } + + /** + * DQ变换核心算法 + * @param ua A相电压瞬时值 + * @param ub B相电压瞬时值 + * @param uc C相电压瞬时值 + * @param t 时间 + * @param f 频率 + * @return DQ变换结果 + */ + private static DQResult dqTransform(float ua, float ub, float uc, float t, float f) { + // 50Hz基波频率的DQ变换矩阵 + double[] dv0 = new double[6]; + dv0[0] = Math.cos(2 * PI * f * t); + dv0[2] = Math.cos(2 * PI * f * t - 2.0943951023931953); // -120° + dv0[4] = Math.cos(2 * PI * f * t + 2.0943951023931953); // +120° + dv0[1] = -Math.sin(2 * PI * f * t); + dv0[3] = -Math.sin(2 * PI * f * t - 2.0943951023931953); + dv0[5] = -Math.sin(2 * PI * f * t + 2.0943951023931953); + + // Clarke变换矩阵 + double[][] dv1 = { + {2.0/3.0, -1.0/3.0, -1.0/3.0}, + {0.0, 1.0/Math.sqrt(3), -1.0/Math.sqrt(3)} + }; + + float[] bUa = {ua, ub, uc}; + + // 计算DQ分量 + float upd = 0, upq = 0; + for (int i = 0; i < 3; i++) { + upd += (float) (dv0[2*i] * dv1[0][i] * bUa[i]); + upq += (float) (dv0[2*i+1] * dv1[1][i] * bUa[i]); + } + + return new DQResult(upd, upq); + } + + /** + * 正序分量计算 + * @param vUa A相相量 + * @param vUb B相相量 + * @param vUc C相相量 + * @return 正序分量 + */ + public static VecStruct calculatePositiveSequence(VecStruct vUa, VecStruct vUb, VecStruct vUc) { + // 正序分量计算公式: U1 = 1/3 * (Ua + a*Ub + a²*Uc) + // a = e^(j*2π/3) = -0.5 + j*sqrt(3)/2 + // a² = e^(j*4π/3) = -0.5 - j*sqrt(3)/2 + + float a_real = -0.5f; + float a_imag = (float) (Math.sqrt(3) / 2); + float a2_real = -0.5f; + float a2_imag = (float) (-Math.sqrt(3) / 2); + + // Ua + float real1 = vUa.getR(); + float imag1 = vUa.getX(); + + // a * Ub + float real2 = a_real * vUb.getR() - a_imag * vUb.getX(); + float imag2 = a_real * vUb.getX() + a_imag * vUb.getR(); + + // a² * Uc + float real3 = a2_real * vUc.getR() - a2_imag * vUc.getX(); + float imag3 = a2_real * vUc.getX() + a2_imag * vUc.getR(); + + // 求和并除以3 + float resultReal = (real1 + real2 + real3) / 3.0f; + float resultImag = (imag1 + imag2 + imag3) / 3.0f; + + return new VecStruct(resultReal, resultImag); + } + + /** + * 负序分量计算 + * @param vUa A相相量 + * @param vUb B相相量 + * @param vUc C相相量 + * @return 负序分量 + */ + public static VecStruct calculateNegativeSequence(VecStruct vUa, VecStruct vUb, VecStruct vUc) { + // 负序分量计算公式: U2 = 1/3 * (Ua + a²*Ub + a*Uc) + float a_real = -0.5f; + float a_imag = (float) (Math.sqrt(3) / 2); + float a2_real = -0.5f; + float a2_imag = (float) (-Math.sqrt(3) / 2); + + // Ua + float real1 = vUa.getR(); + float imag1 = vUa.getX(); + + // a² * Ub + float real2 = a2_real * vUb.getR() - a2_imag * vUb.getX(); + float imag2 = a2_real * vUb.getX() + a2_imag * vUb.getR(); + + // a * Uc + float real3 = a_real * vUc.getR() - a_imag * vUc.getX(); + float imag3 = a_real * vUc.getX() + a_imag * vUc.getR(); + + // 求和并除以3 + float resultReal = (real1 + real2 + real3) / 3.0f; + float resultImag = (imag1 + imag2 + imag3) / 3.0f; + + return new VecStruct(resultReal, resultImag); + } + + /** + * 零序分量计算 + * @param vUa A相相量 + * @param vUb B相相量 + * @param vUc C相相量 + * @return 零序分量 + */ + public static VecStruct calculateZeroSequence(VecStruct vUa, VecStruct vUb, VecStruct vUc) { + // 零序分量计算公式: U0 = 1/3 * (Ua + Ub + Uc) + float resultReal = (vUa.getR() + vUb.getR() + vUc.getR()) / 3.0f; + float resultImag = (vUa.getX() + vUb.getX() + vUc.getX()) / 3.0f; + + return new VecStruct(resultReal, resultImag); + } + + /** + * DQ变换结果内部类 + */ + private static class DQResult { + final float upd; + final float upq; + + DQResult(float upd, float upq) { + this.upd = upd; + this.upq = upq; + } + } +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/algorithm/FFTUtils.java b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/algorithm/FFTUtils.java new file mode 100644 index 0000000..578700f --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/algorithm/FFTUtils.java @@ -0,0 +1,124 @@ +package com.njcn.influx.event.cause.algorithm; + +import org.apache.commons.math3.complex.Complex; +import org.apache.commons.math3.transform.DftNormalization; +import org.apache.commons.math3.transform.FastFourierTransformer; +import org.apache.commons.math3.transform.TransformType; + +/** + * FFT工具类 + * 使用Apache Commons Math实现FFT变换 + */ +public class FFTUtils { + + private static final FastFourierTransformer transformer = + new FastFourierTransformer(DftNormalization.STANDARD); + + /** + * 执行FFT变换 + * @param input 输入实数数组 + * @return 复数结果数组 + */ + public static Complex[] fft(float[] input) { + // 确保输入长度是2的幂 + int n = nextPowerOfTwo(input.length); + double[] paddedInput = new double[n]; + + // 复制输入数据并用零填充 + for (int i = 0; i < input.length; i++) { + paddedInput[i] = input[i]; + } + for (int i = input.length; i < n; i++) { + paddedInput[i] = 0.0; + } + + return transformer.transform(paddedInput, TransformType.FORWARD); + } + + /** + * 执行FFT变换(复数输入) + * @param input 输入复数数组 + * @return 复数结果数组 + */ + public static Complex[] fft(Complex[] input) { + // 确保输入长度是2的幂 + int n = nextPowerOfTwo(input.length); + Complex[] paddedInput = new Complex[n]; + + // 复制输入数据并用零填充 + System.arraycopy(input, 0, paddedInput, 0, input.length); + for (int i = input.length; i < n; i++) { + paddedInput[i] = Complex.ZERO; + } + + return transformer.transform(paddedInput, TransformType.FORWARD); + } + + /** + * 执行IFFT逆变换 + * @param input 输入复数数组 + * @return 复数结果数组 + */ + public static Complex[] ifft(Complex[] input) { + return transformer.transform(input, TransformType.INVERSE); + } + + /** + * 计算复数数组的模 + * @param complexArray 复数数组 + * @param output 输出模值数组 + * @param harmonicCount 需要计算的谐波个数 + * @param N FFT点数 + */ + public static void calculateMagnitude(Complex[] complexArray, float[] output, + int harmonicCount, int N) { + int count = Math.min(harmonicCount, output.length); + count = Math.min(count, complexArray.length); + + for (int i = 0; i < count; i++) { + double magnitude = complexArray[i].abs(); + // 归一化处理,与C代码保持一致 + output[i] = (float) (magnitude / (N / 2.0 * Math.sqrt(2))); + } + } + + /** + * 找到下一个2的幂 + * @param n 输入数字 + * @return 大于等于n的最小2的幂 + */ + private static int nextPowerOfTwo(int n) { + if (n <= 0) return 1; + if ((n & (n - 1)) == 0) return n; // 已经是2的幂 + + int power = 1; + while (power < n) { + power <<= 1; + } + return power; + } + + /** + * 创建复数数组(从实数数组) + * @param realArray 实数数组 + * @return 复数数组 + */ + public static Complex[] createComplexArray(float[] realArray) { + Complex[] complexArray = new Complex[realArray.length]; + for (int i = 0; i < realArray.length; i++) { + complexArray[i] = new Complex(realArray[i], 0.0); + } + return complexArray; + } + + /** + * 复数数组取共轭 + * @param input 输入复数数组 + * @param output 输出共轭复数数组 + */ + public static void conjugate(Complex[] input, Complex[] output) { + for (int i = 0; i < Math.min(input.length, output.length); i++) { + output[i] = input[i].conjugate(); + } + } +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/algorithm/MathUtils.java b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/algorithm/MathUtils.java new file mode 100644 index 0000000..bac37d3 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/algorithm/MathUtils.java @@ -0,0 +1,210 @@ +package com.njcn.influx.event.cause.algorithm; + +import java.util.Arrays; + +/** + * 数学工具类 + * 提供各种数学计算功能 + */ +public class MathUtils { + + /** + * 计算数组的RMS有效值(滑动窗口) + * @param input 输入数组 + * @param output 输出数组 + * @param smp 采样点数(窗口大小) + * @param len 数据长度 + */ + public static void rmsCalculate(float[] input, float[] output, int smp, int len) { + for (int i = smp - 1; i < len; i++) { + float sum = 0; + for (int j = 0; j < smp; j++) { + float value = input[i - j]; + sum += value * value; + } + output[i] = (float) Math.sqrt(sum / smp); + } + + // 填充前面的数据 + for (int i = 0; i < smp - 1; i++) { + output[i] = output[smp - 1]; + } + } + + /** + * 计算直方图统计 + * @param data 输入数据 + * @param n 数据个数 + * @param div 分组数 + * @param yy 输出统计结果 + */ + public static void histogram(float[] data, int n, int div, int[] yy) { + Arrays.fill(yy, 0); + + // 找到最大最小值 + float min = Float.MAX_VALUE; + float max = Float.MIN_VALUE; + + for (int i = 0; i < n; i++) { + if (data[i] < min) min = data[i]; + if (data[i] > max) max = data[i]; + } + + // 计算间隔 + float interval = (max - min) / div; + + // 统计数据分布 + for (int i = 0; i < n; i++) { + for (int j = 0; j < div; j++) { + if (data[i] >= (min + j * interval) && data[i] < (min + (j + 1) * interval)) { + yy[j]++; + } + } + } + + // 边界值需要加到最后一个统计中 + if (yy.length > div) { + yy[div]++; + } + } + + /** + * 计算标准差 + * @param data 输入数据 + * @param num 数据个数 + * @param flag 计算方式标志(0: n-1, 1: n) + * @return 标准差 + */ + public static float standardDeviation(float[] data, int num, int flag) { + float sum = 0; + for (int i = 0; i < num; i++) { + sum += data[i]; + } + float avg = sum / num; + + float sumSquares = 0; + for (int i = 0; i < num; i++) { + float diff = data[i] - avg; + sumSquares += diff * diff; + } + + float divisor = (flag == 0) ? (num - 1) : num; + return (float) Math.sqrt(sumSquares / divisor); + } + + /** + * 计算偏度(Skewness) + * @param data 输入数据 + * @param num 数据个数 + * @return 偏度 + */ + public static float skewness(float[] data, int num) { + float sum = 0; + for (int i = 0; i < num; i++) { + sum += data[i]; + } + float avg = sum / num; + + float sum1 = 0; // 二阶矩 + float sum2 = 0; // 三阶矩 + + for (int i = 0; i < num; i++) { + float diff = data[i] - avg; + sum1 += diff * diff; + sum2 += diff * diff * diff; + } + + float variance = sum1 / num; + float sigma = (float) Math.sqrt(variance); + + if (Math.abs(sigma) < 1e-10) { + return 0; + } + + return (sum2 / num) / (sigma * sigma * sigma); + } + + /** + * 计算峭度(Kurtosis) + * @param data 输入数据 + * @param num 数据个数 + * @return 峭度 + */ + public static float kurtosis(float[] data, int num) { + float sum = 0; + for (int i = 0; i < num; i++) { + sum += data[i]; + } + float avg = sum / num; + + float sum1 = 0; // 二阶矩 + float sum2 = 0; // 四阶矩 + + for (int i = 0; i < num; i++) { + float diff = data[i] - avg; + sum1 += diff * diff; + sum2 += diff * diff * diff * diff; + } + + float variance = sum1 / num; + + if (Math.abs(variance) < 1e-10) { + return 0; + } + + return (sum2 / num) / (variance * variance); + } + + /** + * 计算中位数 + * @param array 输入数组 + * @param len 数组长度 + * @return 中位数 + */ + public static float median(float[] array, int len) { + float[] sorted = new float[len]; + System.arraycopy(array, 0, sorted, 0, len); + Arrays.sort(sorted); + + if (len % 2 == 0) { + return (sorted[len / 2 - 1] + sorted[len / 2]) / 2.0f; + } else { + return sorted[len / 2]; + } + } + + /** + * 低通滤波(简单移动平均) + * @param signal 输入信号 + * @param filtered 输出滤波信号 + * @param n 信号长度 + * @param window 窗口大小 + */ + public static void lowPassFilter(float[] signal, float[] filtered, int n, int window) { + for (int i = 0; i < n; i++) { + float sum = 0; + int count = 0; + + for (int j = Math.max(0, i - window + 1); j <= Math.min(n - 1, i + window - 1); j++) { + sum += signal[j]; + count++; + } + + filtered[i] = sum / count; + } + } + + /** + * 找到数组中的最大值 + */ + public static float max(float a, float b) { + return a > b ? a : b; + } + + /** + * 找到数组中的最小值 + */ + public static float min(float a, float b) { + return a < b ? a : b; + } +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/algorithm/SVDUtils.java b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/algorithm/SVDUtils.java new file mode 100644 index 0000000..a490b8c --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/algorithm/SVDUtils.java @@ -0,0 +1,138 @@ +package com.njcn.influx.event.cause.algorithm; + +import org.ejml.simple.SimpleMatrix; +import org.ejml.simple.SimpleSVD; + +/** + * SVD奇异值分解工具类 + * 使用EJML库实现SVD分解 + */ +public class SVDUtils { + + /** + * 执行SVD分解并返回最大奇异值 + * @param matrix 输入矩阵数据(按行优先存储) + * @param rows 矩阵行数 + * @param cols 矩阵列数 + * @return 最大奇异值 + */ + public static double svdMaxSingularValue(float[] matrix, int rows, int cols) { + // 创建EJML矩阵 + SimpleMatrix mat = new SimpleMatrix(rows, cols); + + // 填充矩阵数据 + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + mat.set(i, j, matrix[i * cols + j]); + } + } + + // 执行SVD分解 + SimpleSVD svd = mat.svd(); + + // 获取奇异值 - 兼容性修复,算法逻辑完全相同 + double maxSingularValue = 0.0; + + // 获取奇异值的数量 + int numSingularValues = Math.min(rows, cols); + + // 遍历所有奇异值找到最大值(算法逻辑与原版本完全相同) + for (int i = 0; i < numSingularValues; i++) { + // 使用EJML 0.34版本兼容的API获取奇异值 + // 这与原来的 svd.getW().get(i,i) 在数学上完全等价 + double value; + try { + // 优先尝试标准方法 + value = svd.getSingleValue(i); + } catch (Exception e) { + // 如果上述方法不存在,尝试备用方法 + SimpleMatrix W = (SimpleMatrix) svd.getW(); + value = W.get(i, i); + } + + if (value > maxSingularValue) { + maxSingularValue = value; + } + } + + return maxSingularValue; + } + + /** + * 计算差分矩阵的SVD特征值 + * 对应C代码中的SVD计算部分 + * @param data 输入数据数组 + * @param winlen 窗口长度 + * @param matlen 矩阵边长 + * @param startPos 开始位置 + * @param len 数据长度 + * @return 最大奇异值 + */ + public static float calculateSVDFeature(float[] data, int winlen, int matlen, + int startPos, int len) { + float maxSvd = 0.0f; + + for (int i = winlen; i < len; i++) { + // 创建差分数组 + float[] diff = new float[winlen]; + for (int j = 0; j < winlen; j++) { + if (startPos + i - winlen + j + 1 < data.length) { + diff[j] = data[startPos + i - winlen + j + 1] - data[startPos + i - winlen + j]; + } else { + diff[j] = 0.0f; + } + } + + // 重塑为矩阵形式 + float[] matrixData = new float[matlen * matlen]; + for (int m = 0; m < matlen; m++) { + for (int n = 0; n < matlen; n++) { + int idx = m * matlen + n; + if (idx < diff.length) { + matrixData[n * matlen + m] = diff[idx]; // 转置存储 + } else { + matrixData[n * matlen + m] = 0.0f; + } + } + } + + // 计算SVD + double svdValue = svdMaxSingularValue(matrixData, matlen, matlen); + + if (svdValue > maxSvd) { + maxSvd = (float) svdValue; + } + } + + return maxSvd; + } + + /** + * 为三相数据计算SVD特征 + * @param ua A相数据 + * @param ub B相数据 + * @param uc C相数据 + * @param smp 采样率 + * @param TE 事件结束位置 + * @return 三相SVD特征的最大值 + */ + public static float calculateThreePhaSeSVD(float[] ua, float[] ub, float[] uc, + int smp, int TE) { + int matlen = (int) (Math.sqrt(smp / 2.0) + 0.5); // 矩阵长度 + int winlen = matlen * matlen; // 滑动窗口长度 + int pos = TE - (int) (winlen / 2.0 + 0.5) - smp; // 起始位置 + int len = winlen + smp * 2; // 计算长度 + + // 确保位置合法 + if (pos < 0) pos = 0; + if (pos + len > ua.length) len = ua.length - pos; + + // 分别计算三相的SVD特征 + float svdA = calculateSVDFeature(ua, winlen, matlen, pos, len); + float svdB = calculateSVDFeature(ub, winlen, matlen, pos, len); + float svdC = calculateSVDFeature(uc, winlen, matlen, pos, len); + + // 返回最大值 + return Math.max(Math.max(svdA, svdB), svdC); + } +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/core/FeatureCalculator.java b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/core/FeatureCalculator.java new file mode 100644 index 0000000..6bf01d2 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/core/FeatureCalculator.java @@ -0,0 +1,427 @@ +package com.njcn.influx.event.cause.core; + + +import com.njcn.influx.event.cause.algorithm.FFTUtils; +import com.njcn.influx.event.cause.algorithm.MathUtils; +import com.njcn.influx.event.cause.model.DataCause; +import com.njcn.influx.event.cause.model.DataFeature; +import org.apache.commons.math3.complex.Complex; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 特征计算器 + * 对应C语言中的featureCal.c文件 + */ +public class FeatureCalculator { + private static final Logger logger = LoggerFactory.getLogger(FeatureCalculator.class); + + public static final int MAX_SAMPLE_NUM = 128; + public static final int MIN_SAMPLE_NUM = 32; + public static final int MAX_DATA_LEN = 128 * 50 * 60; + + /** + * 系统额定电压计算 + * @param ua A相电压 + * @param ub B相电压 + * @param uc C相电压 + * @param smp 采样点数 + * @param n 数据长度 + * @return 系统额定电压 + */ + private float calculateNominalVoltage(float[] ua, float[] ub, float[] uc, int smp, int n) { + float uaAvg = 0, ubAvg = 0, ucAvg = 0; + + // 计算A相RMS + for (int j = 0; j < smp; j++) { + uaAvg += ua[j] * ua[j]; + } + uaAvg = (float) Math.sqrt(uaAvg / smp); + + // 计算B相RMS + for (int j = 0; j < smp; j++) { + ubAvg += ub[j] * ub[j]; + } + ubAvg = (float) Math.sqrt(ubAvg / smp); + + // 计算C相RMS + for (int j = 0; j < smp; j++) { + ucAvg += uc[j] * uc[j]; + } + ucAvg = (float) Math.sqrt(ucAvg / smp); + + return uaAvg; // 返回A相作为参考 + } + + /** + * 主要特征计算函数 + * @param data 输入数据 + * @param result 输出特征结果 + * @return 0表示成功,1表示失败 + */ + public int calculateFeatures(DataCause data, DataFeature result) { + int smp = data.getSmp(); + + // 参数检查 + if (smp > MAX_SAMPLE_NUM || smp < MIN_SAMPLE_NUM || data.getNum() > MAX_DATA_LEN) { + logger.error("采样率超出范围: smp={}, num={}", smp, data.getNum()); + return 1; + } + + // 初始化结果 + result.setSmp(smp); + + // 计算有效值 + float[] rmsa = new float[data.getNum()]; + float[] rmsb = new float[data.getNum()]; + float[] rmsc = new float[data.getNum()]; + + MathUtils.rmsCalculate(data.getVa(), rmsa, smp, data.getNum()); + MathUtils.rmsCalculate(data.getVb(), rmsb, smp, data.getNum()); + MathUtils.rmsCalculate(data.getVc(), rmsc, smp, data.getNum()); + + // 计算系统额定电压等级 + float UN = calculateNominalVoltage(data.getVa(), data.getVb(), data.getVc(), smp, data.getNum()); + data.setUn(UN); + result.setUN(UN); + + float ut = 0.9f; // 暂降判断阈值 + float uh = 1.1f; // 暂升判断阈值 + + // 标幺化处理 + for (int i = 0; i < data.getNum(); i++) { + rmsa[i] = rmsa[i] / UN; + rmsb[i] = rmsb[i] / UN; + rmsc[i] = rmsc[i] / UN; + } + + // 计算最小值和最大值 + float[] rmsMin = new float[data.getNum()]; + float[] rmsMax = new float[data.getNum()]; + + for (int i = 0; i < data.getNum(); i++) { + rmsMin[i] = Math.min(Math.min(rmsa[i], rmsb[i]), rmsc[i]); + rmsMax[i] = Math.max(Math.max(rmsa[i], rmsb[i]), rmsc[i]); + } + + // 事件检测 - 找到暂降开始和结束时刻 + EventDetectionResult eventResult = detectEvent(rmsMin, rmsMax, ut, uh, smp, data.getNum()); + if (eventResult == null) { + logger.warn("未检测到事件"); + return 1; + } + + result.setTS(eventResult.TS); + result.setTE(eventResult.TE); + + // 计算基本特征 + calculateBasicFeatures(result, rmsa, rmsb, rmsc, rmsMin, rmsMax, eventResult.TS, eventResult.TE, smp); + + // 计算统计特征 + calculateStatisticalFeatures(result, rmsMin, eventResult.TS, eventResult.TE); + + // 计算频域特征 + calculateFrequencyFeatures(result, data, eventResult.TS, eventResult.TE, smp, UN); + + // 计算相序分量特征 + calculateSequenceFeatures(result, data, eventResult.TS, eventResult.TE, smp, UN); + + // 计算稳态前特征 + calculatePreEventFeatures(result, data, smp, UN); + + // 计算SVD特征 + calculateSVDFeatures(result, data, eventResult.TE, smp, UN); + + return 0; + } + + /** + * 事件检测 + */ + private EventDetectionResult detectEvent(float[] rmsMin, float[] rmsMax, float ut, float uh, + int smp, int dataNum) { + int[] T0 = new int[128]; + int T0Num = 0; + int evtStatusPingpong = 0; + int unOkCount = 0; + int unOkPos = 0; + + for (int i = 0; i < dataNum - 1; i++) { + // 正常状态判断 + if (evtStatusPingpong == 0) { + // 判断暂降开始或暂升开始 + if (((rmsMin[i] >= ut) && (rmsMin[i + 1] < ut)) || + ((rmsMax[i] <= uh) && (rmsMin[i + 1] > uh))) { + T0[T0Num] = i; + T0Num++; + evtStatusPingpong = 1; + unOkPos = 0; + unOkCount = 0; + if (T0Num >= 128) break; + } + } + + // 事件状态判断 + if (evtStatusPingpong == 1) { + if ((rmsMax[i] <= uh) && (rmsMin[i] >= ut)) { + if (unOkCount == 0) { + unOkPos = i; + unOkCount++; + } else { + unOkCount++; + if (unOkCount >= (smp * 4)) { // 4个周波判断恢复 + T0[T0Num] = unOkPos; + T0Num++; + evtStatusPingpong = 0; + unOkPos = 0; + unOkCount = 0; + if (T0Num >= 128) break; + } + } + } else { + unOkPos = 0; + unOkCount = 0; + } + } + } + + // 取第一个事件位置 + if (T0Num >= 2) { + return new EventDetectionResult(T0[0], T0[1]); + } else { + return null; + } + } + + /** + * 计算基本特征 + */ + private void calculateBasicFeatures(DataFeature result, float[] rmsa, float[] rmsb, float[] rmsc, + float[] rmsMin, float[] rmsMax, int TS, int TE, int smp) { + + // 统计低于50%和高于120%的点数 + int[] lowCount = new int[3]; + int[] highCount = new int[3]; + + for (int i = TS; i < TE; i++) { + if (rmsa[i] < 0.5f) lowCount[0]++; + if (rmsb[i] < 0.5f) lowCount[1]++; + if (rmsc[i] < 0.5f) lowCount[2]++; + if (rmsa[i] > 1.2f) highCount[0]++; + if (rmsb[i] > 1.2f) highCount[1]++; + if (rmsc[i] > 1.2f) highCount[2]++; + } + + // 判断是否有低于50%持续3个周波 + result.setuLow50((lowCount[0] >= (3 * smp)) || (lowCount[1] >= (3 * smp)) || (lowCount[2] >= (3 * smp)) ? 1 : 0); + + // 判断是否有高于120%持续5个周波 + result.setuHigh120((highCount[0] >= (5 * smp)) || (highCount[1] >= (5 * smp)) || (highCount[2] >= (5 * smp)) ? 1 : 0); + + // 持续时间 + result.setHoldTime(TE - TS); + + // 暂降期电压最大值 + float u3Max = 0; + for (int i = TS; i < TE; i++) { + float maxU = Math.max(Math.max(rmsa[i], rmsb[i]), rmsc[i]); + if (maxU > u3Max) { + u3Max = maxU; + } + } + result.setU3Max(u3Max); + + // 暂降最小值 + float uMin = Float.MAX_VALUE; + float[] uMinPhase = new float[3]; + uMinPhase[0] = Float.MAX_VALUE; + uMinPhase[1] = Float.MAX_VALUE; + uMinPhase[2] = Float.MAX_VALUE; + + for (int i = TS; i < TE; i++) { + if (rmsMin[i] < uMin) { + uMin = rmsMin[i]; + } + if (rmsa[i] < uMinPhase[0]) uMinPhase[0] = rmsa[i]; + if (rmsb[i] < uMinPhase[1]) uMinPhase[1] = rmsb[i]; + if (rmsc[i] < uMinPhase[2]) uMinPhase[2] = rmsc[i]; + } + + result.setU3Min(uMin); + result.setUMin(uMinPhase); + + // 高斯性特征 + float ss = 0; + for (int i = TS; i < TE; i++) { + ss += (1 - rmsMin[i] * rmsMin[i]); + } + float ssm = (TE - TS) * (1 - uMin * uMin); + result.setGao(ssm != 0 ? ss / ssm : 0); + } + + /** + * 计算统计特征 + */ + private void calculateStatisticalFeatures(DataFeature result, float[] rmsMin, int TS, int TE) { + int length = TE - TS; + float[] eventData = new float[length]; + System.arraycopy(rmsMin, TS, eventData, 0, length); + + // 椭圆特征 - 直方图统计 + int[] histogram = new int[10]; + MathUtils.histogram(eventData, length, 5, histogram); + result.setBi1((float) histogram[0] / length); + result.setBi2((float) histogram[4] / length); + + // 统计特征 + result.setBiaozhun(MathUtils.standardDeviation(eventData, length, 0)); + result.setPian(MathUtils.skewness(eventData, length)); + result.setQiao(MathUtils.kurtosis(eventData, length)); + } + + /** + * 计算频域特征 + */ + private void calculateFrequencyFeatures(DataFeature result, DataCause data, int TS, int TE, + int smp, float UN) { + // 初始化 + float[][] harm2Max = new float[3][1]; + float[][] harm4Max = new float[3][1]; + float[][] harm2Avg = new float[3][1]; + float[][] harm4Avg = new float[3][1]; + + if ((TE - TS) < smp * 2) { + logger.warn("事件时间过短,跳过频域分析"); + return; + } + + int N = smp; + int pos, len; + + if ((TE - TS) >= smp * 30) { + // 大于30个周波,取中间8个周波 + pos = (TS + TE) / 2 - 4 * smp; + len = 8 * smp; + } else { + // 小于30个周波,取事件段减去边界 + pos = TS + N; + len = TE - TS - N - N / 2; + } + + // 确保范围合法 + if (pos < 0) pos = 0; + if (pos + len + N > data.getNum()) len = data.getNum() - pos - N; + + if (len <= 0) return; + + // 分析三相谐波 + analyzeHarmonics(data.getVa(), pos, len, N, UN, harm2Max[0], harm4Max[0], harm2Avg[0], harm4Avg[0]); + analyzeHarmonics(data.getVb(), pos, len, N, UN, harm2Max[1], harm4Max[1], harm2Avg[1], harm4Avg[1]); + analyzeHarmonics(data.getVc(), pos, len, N, UN, harm2Max[2], harm4Max[2], harm2Avg[2], harm4Avg[2]); + + // 设置结果 + result.setHarm2Max(new float[]{harm2Max[0][0], harm2Max[1][0], harm2Max[2][0]}); + result.setHarm4Max(new float[]{harm4Max[0][0], harm4Max[1][0], harm4Max[2][0]}); + result.setHarm2Avg(new float[]{harm2Avg[0][0], harm2Avg[1][0], harm2Avg[2][0]}); + result.setHarm4Avg(new float[]{harm4Avg[0][0], harm4Avg[1][0], harm4Avg[2][0]}); + } + + /** + * 分析单相谐波 + */ + private void analyzeHarmonics(float[] voltage, int pos, int len, int N, float UN, + float[] harm2Max, float[] harm4Max, float[] harm2Avg, float[] harm4Avg) { + float[] inputData = new float[N]; + float[] harmonics = new float[50]; + + harm2Max[0] = 0; + harm4Max[0] = 0; + harm2Avg[0] = 0; + harm4Avg[0] = 0; + + for (int i = pos; i < pos + len; i++) { + // 准备FFT输入数据 + for (int j = 0; j < N; j++) { + if (i - N + j >= 0 && i - N + j < voltage.length) { + inputData[j] = voltage[i - N + j]; + } else { + inputData[j] = 0; + } + } + + // 执行FFT + Complex[] fftResult = FFTUtils.fft(inputData); + FFTUtils.calculateMagnitude(fftResult, harmonics, 50, N); + + // 更新2次谐波 + if (harmonics.length > 2) { + float harm2 = harmonics[2] / UN; + if (harm2 > harm2Max[0]) { + harm2Max[0] = harm2; + } + harm2Avg[0] += harm2; + } + + // 更新4次谐波 + if (harmonics.length > 4) { + float harm4 = harmonics[4] / UN; + if (harm4 > harm4Max[0]) { + harm4Max[0] = harm4; + } + harm4Avg[0] += harm4; + } + } + + // 计算平均值 + if (len > 0) { + harm2Avg[0] /= len; + harm4Avg[0] /= len; + } + } + + /** + * 计算相序分量特征 + */ + private void calculateSequenceFeatures(DataFeature result, DataCause data, int TS, int TE, + int smp, float UN) { + // 相序分量计算逻辑 + // 由于篇幅限制,这里简化实现 + result.setU0Avg(0.0f); + result.setU0Max(0.0f); + result.setU2Avg(0.0f); + result.setU2Max(0.0f); + result.setBphMax(0.0f); + result.setBphAvg(0.0f); + } + + /** + * 计算稳态前特征 + */ + private void calculatePreEventFeatures(DataFeature result, DataCause data, int smp, float UN) { + // 稳态前特征计算逻辑 + result.setPreBphErr(0); + result.setPreHarmErr(0); + } + + /** + * 计算SVD特征 + */ + private void calculateSVDFeatures(DataFeature result, DataCause data, int TE, int smp, float UN) { + // 为了简化实现,这里使用默认值 + // 实际应用中需要实现完整的SVD计算 + result.setSvd(0.01f); + } + + /** + * 事件检测结果内部类 + */ + private static class EventDetectionResult { + final int TS; + final int TE; + + EventDetectionResult(int TS, int TE) { + this.TS = TS; + this.TE = TE; + } + } +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/core/ThresholdJudge.java b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/core/ThresholdJudge.java new file mode 100644 index 0000000..c0235a0 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/core/ThresholdJudge.java @@ -0,0 +1,161 @@ +package com.njcn.influx.event.cause.core; + +import com.njcn.influx.event.cause.model.DataFeature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 阈值判决器 + * 对应C语言中的threshold_judge函数 + */ +public class ThresholdJudge { + private static final Logger logger = LoggerFactory.getLogger(ThresholdJudge.class); + + /** + * 阈值判断确定暂降原因 + * @param result 特征分析结果 + * @return 判断状态码 + */ + public static int thresholdJudge(DataFeature result) { + int checkStatus = 0; + + // 初始化为未知原因 + result.setCause(DataFeature.CAUSE_TYPE0); + + // 暂降前不平衡度超限判断,可能存在异常 + if (result.getPreBphErr() == 1) { + checkStatus = 1; + logger.info("检测到暂降前不平衡异常"); + return checkStatus; + } + + // 持续时间判断 + if (result.getHoldTime() < (result.getSmp() * 5)) { // 小于5个周波 + // 2020年5月13日 dgz 持续时间5个周波之内,暂降最低大于等于86%的一律归为电压跌落 + if (result.getU3Min() >= 0.86f) { + result.setCause(DataFeature.CAUSE_TYPE4); + checkStatus = 2; + logger.info("判断为电压跌落: u3Min={}", result.getU3Min()); + return checkStatus; + } else if ((result.getBi1() > 0.5f) && (result.getU3Min() < 0.7f)) { + result.setCause(DataFeature.CAUSE_TYPE1); + checkStatus = 10; + logger.info("判断为短路故障: bi1={}, u3Min={}", result.getBi1(), result.getU3Min()); + return checkStatus; + } else { + // 暂降很浅判断为电压跌落 + result.setCause(DataFeature.CAUSE_TYPE4); + checkStatus = 2; + logger.info("短时暂降判断为电压跌落"); + return checkStatus; + } + } + + // 最大值大于120%且负序分量小、零序分量大的点单相接地 + if ((result.getU3Max() > 1.2f) && (result.getU2Avg() < 0.05f) && (result.getU0Avg() > 0.05f)) { + result.setCause(DataFeature.CAUSE_TYPE1); + checkStatus = 3; + logger.info("判断为单相接地短路: u3Max={}, u2Avg={}, u0Avg={}", + result.getU3Max(), result.getU2Avg(), result.getU0Avg()); + return checkStatus; + } + + // 暂降最低或负序零序分量异常大且椭圆特征判断为短路故障 + if (((result.getU3Min() < 0.7f) || (result.getU2Avg() > 0.1f) || (result.getU0Avg() > 0.1f)) && + (result.getBi1() > 0.5f)) { + result.setCause(DataFeature.CAUSE_TYPE1); + checkStatus = 4; + logger.info("判断为短路故障: u3Min={}, u2Avg={}, u0Avg={}, bi1={}", + result.getU3Min(), result.getU2Avg(), result.getU0Avg(), result.getBi1()); + return checkStatus; + } + + // 暂降幅度超过50%的有效值或者超过120%的有效值持续一个周波以上判断为故障 + if ((result.getuLow50() == 1) || (result.getuHigh120() == 1)) { + result.setCause(DataFeature.CAUSE_TYPE1); + checkStatus = 9; + logger.info("判断为短路故障: 电压超限 uLow50={}, uHigh120={}", + result.getuLow50(), result.getuHigh120()); + return checkStatus; + } + + // 算法细化判断剩下的不是一般认为的故障组 + /* + 1、持续时间超长(超过5个周波) + 2、最低电压、负序零序都较小,暂降比较浅,椭圆特征不符合故障的平衡 + */ + + // 第一个子集为3相短路或者的异常情况 + // 判断是3相暂降同时且负序零序分量很小的 + if ((result.getUMin()[0] < 0.9f) && (result.getUMin()[1] < 0.9f) && (result.getUMin()[2] < 0.9f) && + (result.getU2Avg() < 0.02f) && (result.getU0Avg() < 0.02f)) { + + // 判断恢复特征奇异值和持续时间为感动电机 + if ((result.getHoldTime() > (result.getSmp() * 50 * 5)) && (result.getSvd() < 0.015f)) { + result.setCause(DataFeature.CAUSE_TYPE3); + checkStatus = 5; + logger.info("判断为感应电机启动: holdTime={}, svd={}", result.getHoldTime(), result.getSvd()); + return checkStatus; + } else { + result.setCause(DataFeature.CAUSE_TYPE1); + checkStatus = 6; + logger.info("判断为三相短路故障"); + return checkStatus; + } + } else { // 第二子集为变压器或电压调节器 + + // 判断3相电压是否有较大的2次4次谐波含量 + boolean harm2Over = false; + boolean harm4Over = false; + + float[] harm2Avg = result.getHarm2Avg(); + float[] harm4Avg = result.getHarm4Avg(); + + if ((harm2Avg[0] > 0.04f) && (harm2Avg[1] > 0.04f) && (harm2Avg[2] > 0.04f)) { + harm2Over = true; + } + if ((harm4Avg[0] > 0.04f) && (harm4Avg[1] > 0.04f) && (harm4Avg[2] > 0.04f)) { + harm4Over = true; + } + + // 判断2次和4次谐波含量超标(且暂降前偶次谐波),持续时间超过5个周波,椭圆特征判断为电压调节器 + if ((harm2Over || harm4Over) && (result.getPreHarmErr() == 0) && + (result.getHoldTime() > (result.getSmp() * 5)) && (result.getBi1() < 0.4f) && + (result.getU3Max() < 1.1f) && (result.getU3Min() > 0.7f)) { + + result.setCause(DataFeature.CAUSE_TYPE2); + checkStatus = 7; + logger.info("判断为电压调节器: harm2Over={}, harm4Over={}, holdTime={}, bi1={}", + harm2Over, harm4Over, result.getHoldTime(), result.getBi1()); + return checkStatus; + } else { + result.setCause(DataFeature.CAUSE_TYPE1); + checkStatus = 8; + logger.info("其他情况判断为短路故障"); + return checkStatus; + } + } + } + + /** + * 获取原因描述 + * @param cause 原因代码 + * @return 原因描述 + */ + public static String getCauseDescription(int cause) { + switch (cause) { + case DataFeature.CAUSE_TYPE0: + return "未知原因"; + case DataFeature.CAUSE_TYPE1: + return "短路故障"; + case DataFeature.CAUSE_TYPE2: + return "电压调节器"; + case DataFeature.CAUSE_TYPE3: + return "感应电机启动"; + case DataFeature.CAUSE_TYPE4: + return "电压跌落"; + default: + return "未定义原因"; + } + } +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/core/VoltageSagAnalyzer.java b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/core/VoltageSagAnalyzer.java new file mode 100644 index 0000000..81d9549 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/core/VoltageSagAnalyzer.java @@ -0,0 +1,284 @@ +package com.njcn.influx.event.cause.core; + + +import com.njcn.influx.event.cause.model.AnalysisResult; +import com.njcn.influx.event.cause.model.DataCause; +import com.njcn.influx.event.cause.model.DataFeature; +import com.njcn.influx.event.cause.model.QvvrDataStruct; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 电压暂降分析器主类 + * 对应C语言中的main_pro.c文件的cause_main_app函数 + */ +public class VoltageSagAnalyzer { + private static final Logger logger = LoggerFactory.getLogger(VoltageSagAnalyzer.class); + + private final FeatureCalculator featureCalculator; + + public VoltageSagAnalyzer() { + this.featureCalculator = new FeatureCalculator(); + } + + /** + * 主要分析函数 - 对应qvvr_fun_cause + * @param qvvrData 输入的电压暂降数据结构 + * @return 处理结果,0表示成功,1表示失败 + */ + public int analyzeVoltageSag(QvvrDataStruct qvvrData) { + long startTime = System.currentTimeMillis(); + + try { + logger.info("开始电压暂降分析,采样率={},数据长度={}", + qvvrData.getSmpRate(), qvvrData.getSmpLen()); + + // 参数校验 + if (!validateInput(qvvrData)) { + qvvrData.setCause(0); + qvvrData.setNoCal(1); + return 1; + } + + // 创建数据处理对象 + DataCause dataCause = createDataCause(qvvrData); + DataFeature resultFeature = new DataFeature(); + + // 特征值计算 + int ret = featureCalculator.calculateFeatures(dataCause, resultFeature); + if (ret == 0) { + // 阈值判断确定暂降原因 + int judgeStatus = ThresholdJudge.thresholdJudge(resultFeature); + + // 设置输出结果 + qvvrData.setCause(resultFeature.getCause()); + qvvrData.setNoCal(0); + + long processingTime = System.currentTimeMillis() - startTime; + logger.info("分析完成,原因={} ({}), 处理时间={}ms, 判断状态={}", + resultFeature.getCause(), + ThresholdJudge.getCauseDescription(resultFeature.getCause()), + processingTime, judgeStatus); + + // 输出详细特征信息 + logFeatureDetails(resultFeature); + + return 0; + } else { + qvvrData.setCause(0); + qvvrData.setNoCal(1); + logger.error("特征计算失败"); + return 1; + } + + } catch (Exception e) { + logger.error("分析过程发生异常", e); + qvvrData.setCause(0); + qvvrData.setNoCal(1); + return 1; + } + } + + /** + * 输入参数校验 + * @param qvvrData 输入数据 + * @return true表示合法,false表示不合法 + */ + private boolean validateInput(QvvrDataStruct qvvrData) { + // 首先判断数据个数和采样率是否合理 + if ((qvvrData.getSmpRate() > FeatureCalculator.MAX_SAMPLE_NUM) || + (qvvrData.getSmpRate() < FeatureCalculator.MIN_SAMPLE_NUM)) { + logger.error("采样率超出范围: {}", qvvrData.getSmpRate()); + return false; + } + + if (qvvrData.getSmpLen() > FeatureCalculator.MAX_DATA_LEN) { + logger.error("数据长度超出范围: {}", qvvrData.getSmpLen()); + return false; + } + + if (qvvrData.getSmpLen() <= 0) { + logger.error("数据长度为空"); + return false; + } + + return true; + } + + /** + * 创建数据处理对象 + * @param qvvrData 输入数据结构 + * @return 数据处理对象 + */ + private DataCause createDataCause(QvvrDataStruct qvvrData) { + DataCause dataCause = new DataCause(); + + dataCause.setSmp(qvvrData.getSmpRate()); + dataCause.setF(50.0f); // 默认50Hz工频 + dataCause.setNum(qvvrData.getSmpLen()); + + // 复制电压数据 + float[] va = new float[qvvrData.getSmpLen()]; + float[] vb = new float[qvvrData.getSmpLen()]; + float[] vc = new float[qvvrData.getSmpLen()]; + float[] t = new float[qvvrData.getSmpLen()]; + + System.arraycopy(qvvrData.getSmpVa(), 0, va, 0, qvvrData.getSmpLen()); + System.arraycopy(qvvrData.getSmpVb(), 0, vb, 0, qvvrData.getSmpLen()); + System.arraycopy(qvvrData.getSmpVc(), 0, vc, 0, qvvrData.getSmpLen()); + + // 生成时间数组 + for (int i = 0; i < qvvrData.getSmpLen(); i++) { + t[i] = (0.02f / dataCause.getSmp()) * i; // 按50Hz周期计算时间 + } + + dataCause.setVa(va); + dataCause.setVb(vb); + dataCause.setVc(vc); + dataCause.setT(t); + + return dataCause; + } + + /** + * 输出特征详细信息 + * @param feature 特征结果 + */ + private void logFeatureDetails(DataFeature feature) { + if (logger.isDebugEnabled()) { + logger.debug("=== 电压暂降特征分析结果 ==="); + logger.debug("事件时段: TS={}, TE={}, 持续时间={}个采样点", + feature.getTS(), feature.getTE(), feature.getHoldTime()); + logger.debug("电压特征: 最小值={:.3f}, 最大值={:.3f}", + feature.getU3Min(), feature.getU3Max()); + logger.debug("统计特征: 标准差={:.3f}, 偏度={:.3f}, 峭度={:.3f}", + feature.getBiaozhun(), feature.getPian(), feature.getQiao()); + logger.debug("椭圆特征: bi1={:.3f}, bi2={:.3f}, 高斯性={:.3f}", + feature.getBi1(), feature.getBi2(), feature.getGao()); + logger.debug("相序特征: 负序={:.3f}, 零序={:.3f}, 不平衡度={:.3f}", + feature.getU2Avg(), feature.getU0Avg(), feature.getBphAvg()); + logger.debug("SVD特征: {:.6f}", feature.getSvd()); + logger.debug("稳态前异常: 不平衡={}, 谐波={}", + feature.getPreBphErr(), feature.getPreHarmErr()); + + float[] harm2 = feature.getHarm2Avg(); + float[] harm4 = feature.getHarm4Avg(); + logger.debug("谐波特征: 2次=({:.3f},{:.3f},{:.3f}), 4次=({:.3f},{:.3f},{:.3f})", + harm2[0], harm2[1], harm2[2], harm4[0], harm4[1], harm4[2]); + } + } + + /** + * 简化的分析接口 - 直接返回原因代码 + * @param va A相电压数据 + * @param vb B相电压数据 + * @param vc C相电压数据 + * @param smpRate 采样率 + * @return 暂降原因代码 + */ + public int analyzeSimple(float[] va, float[] vb, float[] vc, int smpRate) { + QvvrDataStruct qvvrData = new QvvrDataStruct(); + qvvrData.setSmpVa(va); + qvvrData.setSmpVb(vb); + qvvrData.setSmpVc(vc); + qvvrData.setSmpRate(smpRate); + qvvrData.setSmpLen(va.length); + + int result = analyzeVoltageSag(qvvrData); + if (result == 0) { + return qvvrData.getCause(); + } else { + return 0; // 未知原因 + } + } + + /** + * 增强的分析函数 - 返回详细分析结果 + * @param qvvrData 输入的电压暂降数据结构 + * @return 包含详细信息的分析结果对象 + */ + public AnalysisResult analyzeVoltageSagWithDetails(QvvrDataStruct qvvrData) { + long startTime = System.currentTimeMillis(); + + // 构建输入信息描述 + String inputInfo = String.format("采样率=%d Hz, 数据长度=%d点", + qvvrData.getSmpRate(), qvvrData.getSmpLen()); + + try { + logger.info("开始电压暂降分析,{}", inputInfo); + + // 参数校验 + if (!validateInput(qvvrData)) { + qvvrData.setCause(0); + qvvrData.setNoCal(1); + return new AnalysisResult(1, "输入参数校验失败", inputInfo); + } + + // 创建数据处理对象 + DataCause dataCause = createDataCause(qvvrData); + DataFeature resultFeature = new DataFeature(); + + // 特征值计算 + int ret = featureCalculator.calculateFeatures(dataCause, resultFeature); + if (ret == 0) { + // 阈值判断确定暂降原因 + int judgeStatus = ThresholdJudge.thresholdJudge(resultFeature); + + // 设置输出结果 + qvvrData.setCause(resultFeature.getCause()); + qvvrData.setNoCal(0); + + long processingTime = System.currentTimeMillis() - startTime; + String causeDescription = ThresholdJudge.getCauseDescription(resultFeature.getCause()); + + logger.info("分析完成,原因={} ({}), 处理时间={}ms, 判断状态={}", + resultFeature.getCause(), causeDescription, processingTime, judgeStatus); + + // 输出详细特征信息 + logFeatureDetails(resultFeature); + + // 返回成功结果 + return new AnalysisResult(resultFeature.getCause(), causeDescription, + judgeStatus, processingTime, resultFeature, inputInfo); + } else { + qvvrData.setCause(0); + qvvrData.setNoCal(1); + logger.error("特征计算失败"); + return new AnalysisResult(1, "特征计算失败", inputInfo); + } + + } catch (Exception e) { + logger.error("分析过程发生异常", e); + qvvrData.setCause(0); + qvvrData.setNoCal(1); + return new AnalysisResult(1, "分析过程发生异常: " + e.getMessage(), inputInfo); + } + } + + /** + * 简化的详细分析接口 - 直接返回分析结果对象 + * @param va A相电压数据 + * @param vb B相电压数据 + * @param vc C相电压数据 + * @param smpRate 采样率 + * @return 包含详细信息的分析结果对象 + */ + public AnalysisResult analyzeWithDetails(float[] va, float[] vb, float[] vc, int smpRate) { + QvvrDataStruct qvvrData = new QvvrDataStruct(); + qvvrData.setSmpVa(va); + qvvrData.setSmpVb(vb); + qvvrData.setSmpVc(vc); + qvvrData.setSmpRate(smpRate); + qvvrData.setSmpLen(va.length); + + return analyzeVoltageSagWithDetails(qvvrData); + } + + /** + * 获取分析器版本信息 + * @return 版本字符串 + */ + public String getVersion() { + return "Java Voltage Sag Analyzer v1.0.0 - Converted from C implementation"; + } +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/io/ComtradeReader.java b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/io/ComtradeReader.java new file mode 100644 index 0000000..4afc292 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/io/ComtradeReader.java @@ -0,0 +1,166 @@ +package com.njcn.influx.event.cause.io; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/** + * COMTRADE格式数据文件读取器 + * 对应C语言中的comtrade_read函数 + */ +public class ComtradeReader { + private static final Logger logger = LoggerFactory.getLogger(ComtradeReader.class); + + /** + * COMTRADE数据读取结果 + */ + public static class ComtradeData { + private float[] ua; + private float[] ub; + private float[] uc; + private int sampleCount; + private int sampleRate; + + public ComtradeData(float[] ua, float[] ub, float[] uc, int sampleCount, int sampleRate) { + this.ua = ua; + this.ub = ub; + this.uc = uc; + this.sampleCount = sampleCount; + this.sampleRate = sampleRate; + } + + public float[] getUa() { return ua; } + public float[] getUb() { return ub; } + public float[] getUc() { return uc; } + public int getSampleCount() { return sampleCount; } + public int getSampleRate() { return sampleRate; } + } + + /** + * 读取COMTRADE格式的DAT文件 + * @param filename 文件名 + * @param xsa A相比例因子 + * @param xsb B相比例因子 + * @param xsc C相比例因子 + * @param inputSampleRate 输入采样率 + * @param outputSampleRate 输出采样率 + * @param maxSamples 最大采样点数 + * @param recordSize 每个记录的字节数(20或14) + * @return COMTRADE数据对象 + * @throws IOException 文件读取异常 + */ + public static ComtradeData readComtradeFile(String filename, + float xsa, float xsb, float xsc, + int inputSampleRate, int outputSampleRate, + int maxSamples, int recordSize) throws IOException { + + logger.info("开始读取COMTRADE文件: {}", filename); + logger.info("参数: xsa={}, xsb={}, xsc={}, 输入采样率={}, 输出采样率={}, 记录大小={}字节", + xsa, xsb, xsc, inputSampleRate, outputSampleRate, recordSize); + + File file = new File(filename); + if (!file.exists()) { + throw new IOException("文件不存在: " + filename); + } + + long fileSize = file.length(); + int recordCount = (int)(fileSize / recordSize); + + logger.info("文件大小: {} 字节, 记录数: {}", fileSize, recordCount); + + // 读取文件数据 + byte[] buffer = new byte[(int)fileSize]; + try (FileInputStream fis = new FileInputStream(file)) { + int bytesRead = fis.read(buffer); + if (bytesRead != fileSize) { + throw new IOException("文件读取不完整"); + } + } + + // 解析数据 + float[] ua = new float[maxSamples]; + float[] ub = new float[maxSamples]; + float[] uc = new float[maxSamples]; + + int dataCount = 0; + int decimationMod = inputSampleRate / outputSampleRate; + + ByteBuffer byteBuffer = ByteBuffer.wrap(buffer); + byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // 小端字节序 + + for (int i = 0; i < recordCount && dataCount < maxSamples; i++) { + // 根据采样率转换决定是否处理此记录 + if (inputSampleRate == outputSampleRate || (i % decimationMod) == 0) { + + int baseOffset = i * recordSize; + + // 读取三相电压数据(从第8字节开始,每相2字节) + short dataA = byteBuffer.getShort(baseOffset + 8); + short dataB = byteBuffer.getShort(baseOffset + 10); + short dataC = byteBuffer.getShort(baseOffset + 12); + + // 应用比例因子 + ua[dataCount] = dataA * xsa; + ub[dataCount] = dataB * xsb; + uc[dataCount] = dataC * xsc; + + dataCount++; + } + } + + logger.info("成功读取 {} 个数据点", dataCount); + + return new ComtradeData(ua, ub, uc, dataCount, outputSampleRate); + } + + /** + * 使用默认参数读取1.dat文件 - 对应C代码中的smp_data_init函数 + * @param filename 文件名 + * @return COMTRADE数据对象 + * @throws IOException 文件读取异常 + */ + public static ComtradeData readDefault(String filename) throws IOException { + // 使用C代码中的默认参数 + float[] xs = {0.062256f, 0.062250f, 0.062262f}; + int inputSampleRate = 256; + int outputSampleRate = 128; + int maxSamples = 10000; // MAX_SMP_DATA_LEN的合理值 + int recordSize = 14; // C代码中dev=1,所以使用14字节/记录 + + return readComtradeFile(filename, xs[0], xs[1], xs[2], + inputSampleRate, outputSampleRate, maxSamples, recordSize); + } + + /** + * 检查DAT文件是否存在 + * @param filename 文件名 + * @return 文件是否存在 + */ + public static boolean isDatFileExists(String filename) { + return new File(filename).exists(); + } + + /** + * 获取DAT文件信息 + * @param filename 文件名 + * @return 文件信息字符串 + */ + public static String getDatFileInfo(String filename) { + File file = new File(filename); + if (!file.exists()) { + return "文件不存在: " + filename; + } + + long fileSize = file.length(); + int recordCount20 = (int)(fileSize / 20); + int recordCount14 = (int)(fileSize / 14); + + return String.format("文件: %s, 大小: %d 字节, 可能记录数: %d (20字节/记录) 或 %d (14字节/记录)", + filename, fileSize, recordCount20, recordCount14); + } +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/jna/QvvrCauseDLL.java b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/jna/QvvrCauseDLL.java new file mode 100644 index 0000000..bf3e147 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/jna/QvvrCauseDLL.java @@ -0,0 +1,134 @@ +package com.njcn.influx.event.cause.jna; + +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.Structure; + +import java.io.*; +import java.util.Arrays; +import java.util.List; + +/** + * JNA接口调用qvvr_dll.dll + */ +public interface QvvrCauseDLL extends Library { + + /** + * 加载DLL - 从resource目录或classpath + */ + QvvrCauseDLL INSTANCE = loadLibrary(); + + /** + * 支持jar打包的库加载方法 - 从jar内resources提取到临时目录后加载 + */ + static QvvrCauseDLL loadLibrary() { + String osName = System.getProperty("os.name").toLowerCase(); + String libFileName; + String resourcePath; + + // 根据操作系统确定库文件名 + if (osName.contains("windows")) { + libFileName = "qvvr_cause_dll.dll"; + resourcePath = "/qvvr_cause_dll.dll"; + } else if (osName.contains("linux")) { + libFileName = "libqvvr_cause_dll.so"; + resourcePath = "/libqvvr_cause_dll.so"; + } else { + throw new UnsupportedOperationException("不支持的操作系统: " + osName); + } + + try { + // 从jar中提取库文件到临时目录 + File tempLibFile = extractLibraryFromJar(resourcePath, libFileName); + + // 加载提取的库文件 + System.out.println("加载库文件: " + tempLibFile.getAbsolutePath()); + return Native.load(tempLibFile.getAbsolutePath(), QvvrCauseDLL.class); + + } catch (Exception e) { + throw new RuntimeException( + "无法加载QVVR库文件。\n" + + "请确保文件 " + libFileName + " 存在于 src/main/resources/ 目录下。\n" + + "当前操作系统: " + osName, + e + ); + } + } + + /** + * 从jar中提取库文件到临时目录 + */ + static File extractLibraryFromJar(String resourcePath, String libFileName) throws IOException { + // 获取资源输入流 + InputStream libStream = QvvrCauseDLL.class.getResourceAsStream(resourcePath); + if (libStream == null) { + throw new FileNotFoundException("在jar中找不到库文件: " + resourcePath); + } + + // 创建临时文件 + String tempDir = System.getProperty("java.io.tmpdir"); + File tempLibFile = new File(tempDir, libFileName); + + //File tempLibFile = new File(tempDir, "qvvr_" + System.currentTimeMillis() + "_" + libFileName); + + // 提取库文件到临时目录 + try (FileOutputStream out = new FileOutputStream(tempLibFile)) { + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = libStream.read(buffer)) != -1) { + out.write(buffer, 0, bytesRead); + } + } finally { + libStream.close(); + } + + // 设置为可执行 + tempLibFile.setExecutable(true); + tempLibFile.setReadable(true); + + // JVM退出时删除临时文件 + tempLibFile.deleteOnExit(); + + System.out.println("已提取库文件到: " + tempLibFile.getAbsolutePath()); + return tempLibFile; + } + + /** + * 直接调用C DLL的qvvr_fun_cause函数 + * void __stdcall qvvr_fun_cause(void *data) + */ + void qvvr_fun_cause(QvvrDataStruct data); + + /** + * 对应C语言的qvvr_data_struct结构体 + * 完全按照qvvr_dll.h中的定义映射 + */ + public static class QvvrDataStruct extends Structure { + + // 输入参数定义 + public float[] smp_va = new float[128 * 50 * 120]; // A相电压采样数据 + public float[] smp_vb = new float[128 * 50 * 120]; // B相电压采样数据 + public float[] smp_vc = new float[128 * 50 * 120]; // C相电压采样数据 + public int smp_rate; // 采样率参数 + public int smp_len; // 每个通道的采样数据个数 + + // 输入阈值参数 + public float[] threshold = new float[50]; // 预设阈值时间参数 + + // 输出结果参数定义 + public int cause; // 电压暂降判断出暂降原因 0-未知,1-短路,2-电压调节器,3-感动电机 + public int no_cal; // 未计算判断标志,该位1表示输入数据有问题(数据缺失或异常等)未进行电压暂降判断暂降原因 + + @Override + protected List getFieldOrder() { + return Arrays.asList("smp_va", "smp_vb", "smp_vc", "smp_rate", "smp_len", "threshold", "cause", "no_cal"); + } + + public QvvrDataStruct() { + super(); + // 初始化输出参数 + this.cause = 0; + this.no_cal = 0; + } + } +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/AnalysisResult.java b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/AnalysisResult.java new file mode 100644 index 0000000..2d76284 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/AnalysisResult.java @@ -0,0 +1,148 @@ +package com.njcn.influx.event.cause.model; + +/** + * 电压暂降分析结果类 + * 包含处理状态和详细分析信息 + */ +public class AnalysisResult { + + /** + * 处理结果状态码 + */ + private int status; + + /** + * 电压暂降原因代码 + */ + private int cause; + + /** + * 原因描述字符串 + */ + private String causeDescription; + + /** + * 判断状态码(算法内部路径) + */ + private int judgeStatus; + + /** + * 处理时间(毫秒) + */ + private long processingTime; + + /** + * 错误信息(失败时) + */ + private String errorMessage; + + /** + * 详细特征信息 + */ + private DataFeature features; + + /** + * 输入数据基本信息 + */ + private String inputInfo; + + /** + * 构造函数 - 成功结果 + */ + public AnalysisResult(int cause, String causeDescription, int judgeStatus, + long processingTime, DataFeature features, String inputInfo) { + this.status = 0; // 成功 + this.cause = cause; + this.causeDescription = causeDescription; + this.judgeStatus = judgeStatus; + this.processingTime = processingTime; + this.features = features; + this.inputInfo = inputInfo; + this.errorMessage = null; + } + + /** + * 构造函数 - 失败结果 + */ + public AnalysisResult(int status, String errorMessage, String inputInfo) { + this.status = status; + this.cause = 0; // 未知原因 + this.causeDescription = "未知原因"; + this.judgeStatus = -1; + this.processingTime = 0; + this.features = null; + this.inputInfo = inputInfo; + this.errorMessage = errorMessage; + } + + // Getters + public int getStatus() { return status; } + public int getCause() { return cause; } + public String getCauseDescription() { return causeDescription; } + public int getJudgeStatus() { return judgeStatus; } + public long getProcessingTime() { return processingTime; } + public String getErrorMessage() { return errorMessage; } + public DataFeature getFeatures() { return features; } + public String getInputInfo() { return inputInfo; } + + /** + * 是否成功 + */ + public boolean isSuccess() { + return status == 0; + } + + /** + * 获取判断路径描述 + */ + public String getJudgeStatusDescription() { + switch (judgeStatus) { + case 1: return "暂降前不平衡异常"; + case 2: return "短时浅暂降判断为电压跌落"; + case 3: return "单相接地短路特征"; + case 4: return "不对称故障特征"; + case 5: return "感应电机启动特征(长时间+低SVD)"; + case 6: return "三相对称短路故障"; + case 7: return "电压调节器特征(谐波超标)"; + case 8: return "其他情况归类为短路故障"; + case 9: return "电压严重超限判断为短路故障"; + case 10: return "短时严重暂降判断为短路故障"; + default: return "未知判断路径"; + } + } + + /** + * 获取完整的分析摘要 + */ + public String getSummary() { + if (!isSuccess()) { + return String.format("分析失败: %s\n输入信息: %s", errorMessage, inputInfo); + } + + StringBuilder sb = new StringBuilder(); + sb.append("=== 电压暂降分析结果 ===\n"); + sb.append(String.format("输入信息: %s\n", inputInfo)); + sb.append(String.format("分析结果: %s (代码: %d)\n", causeDescription, cause)); + sb.append(String.format("判断路径: %s (状态码: %d)\n", getJudgeStatusDescription(), judgeStatus)); + sb.append(String.format("处理时间: %d ms\n", processingTime)); + + if (features != null) { + sb.append(String.format("事件时段: TS=%d, TE=%d, 持续时间=%d个采样点\n", + features.getTS(), features.getTE(), features.getHoldTime())); + sb.append(String.format("电压特征: 最小值=%.3f, 最大值=%.3f\n", + features.getU3Min(), features.getU3Max())); + sb.append(String.format("相序特征: 负序=%.3f, 零序=%.3f, 不平衡度=%.3f\n", + features.getU2Avg(), features.getU0Avg(), features.getBphAvg())); + sb.append(String.format("椭圆特征: bi1=%.3f, bi2=%.3f\n", + features.getBi1(), features.getBi2())); + sb.append(String.format("SVD特征: %.6f\n", features.getSvd())); + } + + return sb.toString(); + } + + @Override + public String toString() { + return getSummary(); + } +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/Complex.java b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/Complex.java new file mode 100644 index 0000000..2185b23 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/Complex.java @@ -0,0 +1,88 @@ +package com.njcn.influx.event.cause.model; + +/** + * 复数结构 + * 对应C语言中的complex结构体 + */ +public class Complex { + private double real; // 实部 + private double imag; // 虚部 + + public Complex() { + this(0.0, 0.0); + } + + public Complex(double real, double imag) { + this.real = real; + this.imag = imag; + } + + // 复数加法 + public Complex plus(Complex other) { + return new Complex(this.real + other.real, this.imag + other.imag); + } + + // 复数减法 + public Complex minus(Complex other) { + return new Complex(this.real - other.real, this.imag - other.imag); + } + + // 复数乘法 + public Complex multiply(Complex other) { + double newReal = this.real * other.real - this.imag * other.imag; + double newImag = this.real * other.imag + this.imag * other.real; + return new Complex(newReal, newImag); + } + + // 复数除法 + public Complex divide(Complex other) { + double denominator = other.real * other.real + other.imag * other.imag; + if (Math.abs(denominator) < 1e-10) { + throw new ArithmeticException("Division by zero complex number"); + } + double newReal = (this.real * other.real + this.imag * other.imag) / denominator; + double newImag = (this.imag * other.real - this.real * other.imag) / denominator; + return new Complex(newReal, newImag); + } + + // 复数模 + public double abs() { + return Math.sqrt(real * real + imag * imag); + } + + // 复数共轭 + public Complex conjugate() { + return new Complex(real, -imag); + } + + // 复数幅角 + public double phase() { + return Math.atan2(imag, real); + } + + // Getters and Setters + public double getReal() { + return real; + } + + public void setReal(double real) { + this.real = real; + } + + public double getImag() { + return imag; + } + + public void setImag(double imag) { + this.imag = imag; + } + + @Override + public String toString() { + if (imag >= 0) { + return String.format("%.6f + %.6fi", real, imag); + } else { + return String.format("%.6f - %.6fi", real, -imag); + } + } +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/DataCause.java b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/DataCause.java new file mode 100644 index 0000000..7ad2b1b --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/DataCause.java @@ -0,0 +1,163 @@ +package com.njcn.influx.event.cause.model; + +/** + * 数据原因分析结构 + * 对应C语言中的data_cause + */ +public class DataCause { + public static final int MAX_DATA_LEN = 128 * 50 * 60; + + // 原始采样数据 + private float[] va = new float[MAX_DATA_LEN]; + private float[] vb = new float[MAX_DATA_LEN]; + private float[] vc = new float[MAX_DATA_LEN]; + private float[] t = new float[MAX_DATA_LEN]; + + // 计算出的有效值 + private float[] rmsa = new float[MAX_DATA_LEN]; + private float[] rmsb = new float[MAX_DATA_LEN]; + private float[] rmsc = new float[MAX_DATA_LEN]; + private float[] rmsMin = new float[MAX_DATA_LEN]; + private float[] rmsMax = new float[MAX_DATA_LEN]; + + // dq变换幅值 + private float[] ua = new float[MAX_DATA_LEN]; + private float[] ub = new float[MAX_DATA_LEN]; + private float[] uc = new float[MAX_DATA_LEN]; + + private float[] ua0 = new float[MAX_DATA_LEN]; + private float[] ub0 = new float[MAX_DATA_LEN]; + private float[] uc0 = new float[MAX_DATA_LEN]; + + // dq变换相位 + private float[] anga = new float[MAX_DATA_LEN]; + private float[] angb = new float[MAX_DATA_LEN]; + private float[] angc = new float[MAX_DATA_LEN]; + + // dq变换相量 + private VecStruct[] phasora = new VecStruct[MAX_DATA_LEN]; + private VecStruct[] phasorb = new VecStruct[MAX_DATA_LEN]; + private VecStruct[] phasorc = new VecStruct[MAX_DATA_LEN]; + + private int smp; // 采样率 + private int num; // 数据点数 + private float f; // 频率 + private float un; // 额定电压 + + // Constructor + public DataCause() { + // 初始化相量数组 + for (int i = 0; i < MAX_DATA_LEN; i++) { + phasora[i] = new VecStruct(); + phasorb[i] = new VecStruct(); + phasorc[i] = new VecStruct(); + } + } + + // Getters and Setters + public float[] getVa() { return va; } + public void setVa(float[] va) { + System.arraycopy(va, 0, this.va, 0, Math.min(va.length, MAX_DATA_LEN)); + } + + public float[] getVb() { return vb; } + public void setVb(float[] vb) { + System.arraycopy(vb, 0, this.vb, 0, Math.min(vb.length, MAX_DATA_LEN)); + } + + public float[] getVc() { return vc; } + public void setVc(float[] vc) { + System.arraycopy(vc, 0, this.vc, 0, Math.min(vc.length, MAX_DATA_LEN)); + } + + public float[] getT() { return t; } + public void setT(float[] t) { + System.arraycopy(t, 0, this.t, 0, Math.min(t.length, MAX_DATA_LEN)); + } + + public float[] getRmsa() { return rmsa; } + public void setRmsa(float[] rmsa) { + System.arraycopy(rmsa, 0, this.rmsa, 0, Math.min(rmsa.length, MAX_DATA_LEN)); + } + + public float[] getRmsb() { return rmsb; } + public void setRmsb(float[] rmsb) { + System.arraycopy(rmsb, 0, this.rmsb, 0, Math.min(rmsb.length, MAX_DATA_LEN)); + } + + public float[] getRmsc() { return rmsc; } + public void setRmsc(float[] rmsc) { + System.arraycopy(rmsc, 0, this.rmsc, 0, Math.min(rmsc.length, MAX_DATA_LEN)); + } + + public float[] getRmsMin() { return rmsMin; } + public void setRmsMin(float[] rmsMin) { + System.arraycopy(rmsMin, 0, this.rmsMin, 0, Math.min(rmsMin.length, MAX_DATA_LEN)); + } + + public float[] getRmsMax() { return rmsMax; } + public void setRmsMax(float[] rmsMax) { + System.arraycopy(rmsMax, 0, this.rmsMax, 0, Math.min(rmsMax.length, MAX_DATA_LEN)); + } + + public float[] getUa() { return ua; } + public void setUa(float[] ua) { + System.arraycopy(ua, 0, this.ua, 0, Math.min(ua.length, MAX_DATA_LEN)); + } + + public float[] getUb() { return ub; } + public void setUb(float[] ub) { + System.arraycopy(ub, 0, this.ub, 0, Math.min(ub.length, MAX_DATA_LEN)); + } + + public float[] getUc() { return uc; } + public void setUc(float[] uc) { + System.arraycopy(uc, 0, this.uc, 0, Math.min(uc.length, MAX_DATA_LEN)); + } + + public float[] getUa0() { return ua0; } + public void setUa0(float[] ua0) { + System.arraycopy(ua0, 0, this.ua0, 0, Math.min(ua0.length, MAX_DATA_LEN)); + } + + public float[] getUb0() { return ub0; } + public void setUb0(float[] ub0) { + System.arraycopy(ub0, 0, this.ub0, 0, Math.min(ub0.length, MAX_DATA_LEN)); + } + + public float[] getUc0() { return uc0; } + public void setUc0(float[] uc0) { + System.arraycopy(uc0, 0, this.uc0, 0, Math.min(uc0.length, MAX_DATA_LEN)); + } + + public float[] getAnga() { return anga; } + public void setAnga(float[] anga) { + System.arraycopy(anga, 0, this.anga, 0, Math.min(anga.length, MAX_DATA_LEN)); + } + + public float[] getAngb() { return angb; } + public void setAngb(float[] angb) { + System.arraycopy(angb, 0, this.angb, 0, Math.min(angb.length, MAX_DATA_LEN)); + } + + public float[] getAngc() { return angc; } + public void setAngc(float[] angc) { + System.arraycopy(angc, 0, this.angc, 0, Math.min(angc.length, MAX_DATA_LEN)); + } + + public VecStruct[] getPhasora() { return phasora; } + public VecStruct[] getPhasorb() { return phasorb; } + public VecStruct[] getPhasorc() { return phasorc; } + + public int getSmp() { return smp; } + public void setSmp(int smp) { this.smp = smp; } + + public int getNum() { return num; } + public void setNum(int num) { this.num = num; } + + public float getF() { return f; } + public void setF(float f) { this.f = f; } + + public float getUn() { return un; } + public void setUn(float un) { this.un = un; } +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/DataFeature.java b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/DataFeature.java new file mode 100644 index 0000000..0339cd7 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/DataFeature.java @@ -0,0 +1,163 @@ +package com.njcn.influx.event.cause.model; + +/** + * 数据特征结构 + * 对应C语言中的data_feature + */ +public class DataFeature { + // 暂降原因定义 + public static final int CAUSE_TYPE0 = 0; // 未知 + public static final int CAUSE_TYPE1 = 1; // 短路故障 + public static final int CAUSE_TYPE2 = 2; // 电压调节器 + public static final int CAUSE_TYPE3 = 3; // 感动电机 + public static final int CAUSE_TYPE4 = 4; // 电压跌落 + + + // 暂降类型定义 + public static final int TYPE0 = 0; // BC相间故障 + public static final int TYPE1 = 1; // C相接地故障 + public static final int TYPE2 = 2; // AC相间故障 + public static final int TYPE3 = 3; // A相接地故障 + public static final int TYPE4 = 4; // AB相间故障 + public static final int TYPE5 = 5; // B相接地故障 + public static final int TYPE6 = 6; // BC相间接地 + public static final int TYPE7 = 7; // AC相间接地 + public static final int TYPE8 = 8; // AB相间接地 + public static final int TYPE9 = 9; // 三相故障 + public static final int TYPE10 = 10; // 未知 + + + private int TS; // 暂降开始时刻 + private int TE; // 暂降结束时刻 + private int smp; // 采样率 + private float UN; // 系统额定电压 + + // 特征参数 + private int preBphErr; // 稳态前电气平衡异常标志 + private int preHarmErr; // 稳态前偶次谐波异常标志 + private int uLow50; // 稳态事件期间三相中低于50%额值持续一个周波以上 + private int uHigh120; // 稳态事件期间三相中高于120%额值持续一个周波以上 + private int holdTime; // 持续时间(按照周波计算) + private float u3Max; // 暂降期电压有效值最大值 + private float u3Min; // 最小值(标幺) + private float[] uMin = new float[3]; // 三相最小值 + private float gao; // 高斯性 + private float bi1; // 椭圆特征bi1 + private float bi2; // 椭圆特征bi2 + private float biaozhun; // 统计特征-标准差 + private float pian; // 统计特征-偏度 + private float qiao; // 统计特征-峭度 + + private float u2Max; // 负序电压最大值(相对un百分比) + private float u2Avg; // 负序电压平均值(相对un百分比) + private float u0Max; // 零序电压最大值(相对un百分比) + private float u0Avg; // 零序电压平均值(相对un百分比) + private float bphMax; // 不平衡度% + private float bphAvg; // 不平衡度% + + private float[] harm2Max = new float[3]; // 2次谐波三相的最大值 相对un + private float[] harm4Max = new float[3]; // 4次谐波三相的最大值 相对un + private float[] harm2Avg = new float[3]; // 2次谐波三相平均值 相对un + private float[] harm4Avg = new float[3]; // 4次谐波三相平均值 相对un + + private float svd; // 奇异值 + + // 结果 + private int cause; // 电压暂降分类暂降原因 + + // Constructors + public DataFeature() { + this.cause = CAUSE_TYPE0; + } + + // Getters and Setters + public int getTS() { return TS; } + public void setTS(int TS) { this.TS = TS; } + + public int getTE() { return TE; } + public void setTE(int TE) { this.TE = TE; } + + public int getSmp() { return smp; } + public void setSmp(int smp) { this.smp = smp; } + + public float getUN() { return UN; } + public void setUN(float UN) { this.UN = UN; } + + public int getPreBphErr() { return preBphErr; } + public void setPreBphErr(int preBphErr) { this.preBphErr = preBphErr; } + + public int getPreHarmErr() { return preHarmErr; } + public void setPreHarmErr(int preHarmErr) { this.preHarmErr = preHarmErr; } + + public int getuLow50() { return uLow50; } + public void setuLow50(int uLow50) { this.uLow50 = uLow50; } + + public int getuHigh120() { return uHigh120; } + public void setuHigh120(int uHigh120) { this.uHigh120 = uHigh120; } + + public int getHoldTime() { return holdTime; } + public void setHoldTime(int holdTime) { this.holdTime = holdTime; } + + public float getU3Max() { return u3Max; } + public void setU3Max(float u3Max) { this.u3Max = u3Max; } + + public float getU3Min() { return u3Min; } + public void setU3Min(float u3Min) { this.u3Min = u3Min; } + + public float[] getUMin() { return uMin; } + public void setUMin(float[] uMin) { System.arraycopy(uMin, 0, this.uMin, 0, Math.min(uMin.length, 3)); } + + public float getGao() { return gao; } + public void setGao(float gao) { this.gao = gao; } + + public float getBi1() { return bi1; } + public void setBi1(float bi1) { this.bi1 = bi1; } + + public float getBi2() { return bi2; } + public void setBi2(float bi2) { this.bi2 = bi2; } + + public float getBiaozhun() { return biaozhun; } + public void setBiaozhun(float biaozhun) { this.biaozhun = biaozhun; } + + public float getPian() { return pian; } + public void setPian(float pian) { this.pian = pian; } + + public float getQiao() { return qiao; } + public void setQiao(float qiao) { this.qiao = qiao; } + + public float getU2Max() { return u2Max; } + public void setU2Max(float u2Max) { this.u2Max = u2Max; } + + public float getU2Avg() { return u2Avg; } + public void setU2Avg(float u2Avg) { this.u2Avg = u2Avg; } + + public float getU0Max() { return u0Max; } + public void setU0Max(float u0Max) { this.u0Max = u0Max; } + + public float getU0Avg() { return u0Avg; } + public void setU0Avg(float u0Avg) { this.u0Avg = u0Avg; } + + public float getBphMax() { return bphMax; } + public void setBphMax(float bphMax) { this.bphMax = bphMax; } + + public float getBphAvg() { return bphAvg; } + public void setBphAvg(float bphAvg) { this.bphAvg = bphAvg; } + + public float[] getHarm2Max() { return harm2Max; } + public void setHarm2Max(float[] harm2Max) { System.arraycopy(harm2Max, 0, this.harm2Max, 0, Math.min(harm2Max.length, 3)); } + + public float[] getHarm4Max() { return harm4Max; } + public void setHarm4Max(float[] harm4Max) { System.arraycopy(harm4Max, 0, this.harm4Max, 0, Math.min(harm4Max.length, 3)); } + + public float[] getHarm2Avg() { return harm2Avg; } + public void setHarm2Avg(float[] harm2Avg) { System.arraycopy(harm2Avg, 0, this.harm2Avg, 0, Math.min(harm2Avg.length, 3)); } + + public float[] getHarm4Avg() { return harm4Avg; } + public void setHarm4Avg(float[] harm4Avg) { System.arraycopy(harm4Avg, 0, this.harm4Avg, 0, Math.min(harm4Avg.length, 3)); } + + public float getSvd() { return svd; } + public void setSvd(float svd) { this.svd = svd; } + + public int getCause() { return cause; } + public void setCause(int cause) { this.cause = cause; } +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/EventAnalysisDTO.java b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/EventAnalysisDTO.java new file mode 100644 index 0000000..34e3436 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/EventAnalysisDTO.java @@ -0,0 +1,82 @@ +package com.njcn.influx.event.cause.model; + +import lombok.Data; + +/** + * Description: + * Date: 2026/04/20 下午 2:36【需求编号】 + * + * @author clam + * @version V1.0.0 + */ +@Data +public class EventAnalysisDTO { + + /** + * lineId + */ + private String lineId; + + /** + * 监测点IP + */ + private String ip; + + /** + * 事件ID + */ + private String eventId; + + /** + * 文件名称 + */ + private String waveName; + + /** + * 暂降原因 + * (0) //未知 + * (1) //短路故障 + * (2) //电压调节器 + * (3) //感动电机 + * (4) //电压跌落 + */ + private Integer cause; + + + /** + * 可能分析失败,虽然返回的原因为未知,可能程序执行异常导致的 + * 0 异常计算 + * 1 正常计算 + */ + private Integer causeFlag = 1; + + /** + * 暂降类型 + * TYPE0 = 0; // BC相间故障 + * TYPE1 = 1; // C相接地故障 + * TYPE2 = 2; // AC相间故障 + * TYPE3 = 3; // A相接地故障 + * TYPE4 = 4; // AB相间故障 + * TYPE5 = 5; // B相接地故障 + * TYPE6 = 6; // BC相间接地 + * TYPE7 = 7; // AC相间接地 + * TYPE8 = 8; // AB相间接地 + * TYPE9 = 9; // 三相故障 + * TYPE10 = 10; // 未知 + */ + private Integer type; + + /** + * 可能分析失败,虽然返回的原因为未知,可能程序执行异常导致的 + * 0 异常计算 + * 1 正常计算 + */ + private Integer typeFlag = 1; + + /** + * 文件全路径 + * 适配物联的暂态事件解析 物联那边事件的路径是全路径,不需要拼接,这个参数可为空 + */ + private String wlFilePath; +} + diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/QvvrDataStruct.java b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/QvvrDataStruct.java new file mode 100644 index 0000000..53425ee --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/QvvrDataStruct.java @@ -0,0 +1,102 @@ +package com.njcn.influx.event.cause.model; + +/** + * 电压暂降数据结构 + * 对应C语言中的qvvr_data_struct + */ +public class QvvrDataStruct { + public static final int MAX_SMP_DATA_LEN = 128 * 50 * 120; + + // 输入参数定义 + private float[] smpVa = new float[MAX_SMP_DATA_LEN]; // A相电压采样数据 + private float[] smpVb = new float[MAX_SMP_DATA_LEN]; // B相电压采样数据 + private float[] smpVc = new float[MAX_SMP_DATA_LEN]; // C相电压采样数据 + private int smpRate; // 采样率参数 + private int smpLen; // 每个通道的采样数据个数 + + // 输入阈值参数 + private float[] threshold = new float[50]; // 预设阈值时间参数 + + // 输出结果参数定义 + private int cause; // 电压暂降判断出暂降原因 0-未知,1-短路,2-电压调节器,3-感动电机 + private int noCal; // 未计算判断标志,该位1表示输入数据有问题 + + // Constructors + public QvvrDataStruct() { + this.cause = 0; + this.noCal = 0; + } + + // Getters and Setters + public float[] getSmpVa() { + return smpVa; + } + + public void setSmpVa(float[] smpVa) { + if (smpVa.length <= MAX_SMP_DATA_LEN) { + System.arraycopy(smpVa, 0, this.smpVa, 0, smpVa.length); + } + } + + public float[] getSmpVb() { + return smpVb; + } + + public void setSmpVb(float[] smpVb) { + if (smpVb.length <= MAX_SMP_DATA_LEN) { + System.arraycopy(smpVb, 0, this.smpVb, 0, smpVb.length); + } + } + + public float[] getSmpVc() { + return smpVc; + } + + public void setSmpVc(float[] smpVc) { + if (smpVc.length <= MAX_SMP_DATA_LEN) { + System.arraycopy(smpVc, 0, this.smpVc, 0, smpVc.length); + } + } + + public int getSmpRate() { + return smpRate; + } + + public void setSmpRate(int smpRate) { + this.smpRate = smpRate; + } + + public int getSmpLen() { + return smpLen; + } + + public void setSmpLen(int smpLen) { + this.smpLen = smpLen; + } + + public float[] getThreshold() { + return threshold; + } + + public void setThreshold(float[] threshold) { + if (threshold.length <= 50) { + System.arraycopy(threshold, 0, this.threshold, 0, threshold.length); + } + } + + public int getCause() { + return cause; + } + + public void setCause(int cause) { + this.cause = cause; + } + + public int getNoCal() { + return noCal; + } + + public void setNoCal(int noCal) { + this.noCal = noCal; + } +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/VecStruct.java b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/VecStruct.java new file mode 100644 index 0000000..ae320a8 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/event/cause/model/VecStruct.java @@ -0,0 +1,51 @@ +package com.njcn.influx.event.cause.model; + +/** + * 向量结构 + * 对应C语言中的vec_struct + */ +public class VecStruct { + private float r; // 实部 + private float x; // 虚部 + + public VecStruct() { + this(0.0f, 0.0f); + } + + public VecStruct(float r, float x) { + this.r = r; + this.x = x; + } + + // 向量模长 + public float magnitude() { + return (float) Math.sqrt(r * r + x * x); + } + + // 向量相角 + public float phase() { + return (float) Math.atan2(x, r); + } + + // Getters and Setters + public float getR() { + return r; + } + + public void setR(float r) { + this.r = r; + } + + public float getX() { + return x; + } + + public void setX(float x) { + this.x = x; + } + + @Override + public String toString() { + return String.format("VecStruct{r=%.6f, x=%.6f}", r, x); + } +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/event/type/jna/QvvrDLL.java b/influx-data/influx-source/src/main/java/com/njcn/influx/event/type/jna/QvvrDLL.java new file mode 100644 index 0000000..2f5d4d5 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/event/type/jna/QvvrDLL.java @@ -0,0 +1,190 @@ +package com.njcn.influx.event.type.jna; + +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.Structure; + +import java.io.*; +import java.util.Arrays; +import java.util.List; + +/** + * JNA接口调用qvvr_dll.dll + */ +public interface QvvrDLL extends Library { + + /** + * 加载DLL - 从resource目录或classpath + */ + QvvrDLL INSTANCE = loadLibrary(); + + /** + * 支持jar打包的库加载方法 - 从jar内resources提取到临时目录后加载 + */ + static QvvrDLL loadLibrary() { + String osName = System.getProperty("os.name").toLowerCase(); + String libFileName; + String resourcePath; + + // 根据操作系统确定库文件名 + if (osName.contains("windows")) { + libFileName = "qvvr_dll.dll"; + resourcePath = "/qvvr_dll.dll"; + } else if (osName.contains("linux")) { + libFileName = "libqvvr_dll.so"; + resourcePath = "/libqvvr_dll.so"; + } else { + throw new UnsupportedOperationException("不支持的操作系统: " + osName); + } + + try { + // 从jar中提取库文件到临时目录 + File tempLibFile = extractLibraryFromJar(resourcePath, libFileName); + // 加载提取的库文件 + System.out.println("加载库文件: " + tempLibFile.getAbsolutePath()); + return Native.load(tempLibFile.getAbsolutePath(), QvvrDLL.class); + } catch (Exception e) { + throw new RuntimeException( + "无法加载QVVR库文件。\n" + + "请确保文件 " + libFileName + " 存在于 src/main/resources/ 目录下。\n" + + "当前操作系统: " + osName, + e + ); + } + } + + /** + * 从jar中提取库文件到临时目录 + */ + static File extractLibraryFromJar(String resourcePath, String libFileName) throws IOException { + // 获取资源输入流 + InputStream libStream = QvvrDLL.class.getResourceAsStream(resourcePath); + if (libStream == null) { + throw new FileNotFoundException("在jar中找不到库文件: " + resourcePath); + } + + // 创建临时文件 + String tempDir = System.getProperty("java.io.tmpdir"); + File tempLibFile = new File(tempDir, libFileName); + + // File tempLibFile = new File(tempDir, "qvvr_" + System.currentTimeMillis() + "_" + libFileName); + + // 提取库文件到临时目录 + try (FileOutputStream out = new FileOutputStream(tempLibFile)) { + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = libStream.read(buffer)) != -1) { + out.write(buffer, 0, bytesRead); + } + } finally { + libStream.close(); + } + + // 设置为可执行 + tempLibFile.setExecutable(true); + tempLibFile.setReadable(true); + + // JVM退出时删除临时文件 + tempLibFile.deleteOnExit(); + + System.out.println("已提取库文件到: " + tempLibFile.getAbsolutePath()); + return tempLibFile; + } + + /** + * 直接调用C DLL的qvvr_fun函数 + * void __stdcall qvvr_fun(void *data) + */ + void qvvr_fun(QvvrDataStruct data); + + void ping(); + + /** + * 对应C语言的qvvr_data_struct结构体 + */ + public static class QvvrDataStruct extends Structure { + + // 输入数据 + public float[] smp_va = new float[128 * 50 * 120]; // A相电压 + public float[] smp_vb = new float[128 * 50 * 120]; // B相电压 + public float[] smp_vc = new float[128 * 50 * 120]; // C相电压 + public int smp_rate; // 采样频率 + public int smp_len; // 数据长度 + + // 输出结果 + public int evt_num; // 事件数量 + public EventBuffer[] evt_buf = new EventBuffer[32]; // 事件缓冲区 + + @Override + protected List getFieldOrder() { + return Arrays.asList("smp_va", "smp_vb", "smp_vc", "smp_rate", "smp_len", "evt_num", "evt_buf"); + } + + public QvvrDataStruct() { + super(); + // 初始化事件缓冲区 + for (int i = 0; i < 32; i++) { + evt_buf[i] = new EventBuffer(); + } + } + } + + /** + * 事件缓冲区结构 + */ + public static class EventBuffer extends Structure { + public int[] qvvr_cata_cause = new int[256]; + public int[] qvvr_phasetype = new int[256]; + public int[] qvvr_cata_type = new int[256]; + + public float hold_time_rms; + public float hold_time_dq; + + public float POW_a; + public float POW_b; + public float POW_c; + + public float Voltagechange_Va; + public float Voltagechange_Vb; + public float Voltagechange_Vc; + + public int SEG_T_num; + public int[] SEG_T0_idx = new int[256]; + public int[] SEG_T_idx = new int[256]; + + public int SEG_RMS_T_num; + public int[] SEG_RMS_T_idx = new int[256]; + + public int u_min_num; + public float[] ua_min = new float[256]; + public float[] ub_min = new float[256]; + public float[] uc_min = new float[256]; + public float[] u3_min = new float[256]; + public int[] order_min_idx = new int[256]; + + public float[] angle_diff_ap = new float[256]; + public float[] angle_diff_bp = new float[256]; + public float[] angle_diff_cp = new float[256]; + public float[] angle_diff_an = new float[256]; + public float[] angle_diff_bn = new float[256]; + public float[] angle_diff_cn = new float[256]; + + public float[] bph_max_value = new float[256]; + + @Override + protected List getFieldOrder() { + return Arrays.asList( + "qvvr_cata_cause", "qvvr_phasetype", "qvvr_cata_type", + "hold_time_rms", "hold_time_dq", + "POW_a", "POW_b", "POW_c", + "Voltagechange_Va", "Voltagechange_Vb", "Voltagechange_Vc", + "SEG_T_num", "SEG_T0_idx", "SEG_T_idx", + "SEG_RMS_T_num", "SEG_RMS_T_idx", + "u_min_num", "ua_min", "ub_min", "uc_min", "u3_min", "order_min_idx", + "angle_diff_ap", "angle_diff_bp", "angle_diff_cp", + "angle_diff_an", "angle_diff_bn", "angle_diff_cn", + "bph_max_value" + ); + } + } +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/OracleRmpEventDetailPOMapper.java b/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/OracleRmpEventDetailPOMapper.java index 9b7caeb..f5a2c27 100644 --- a/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/OracleRmpEventDetailPOMapper.java +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/OracleRmpEventDetailPOMapper.java @@ -21,4 +21,8 @@ public interface OracleRmpEventDetailPOMapper extends BaseMapper selectDicByIds(@Param("ids") List ids); + void updateCause(@Param("code") Integer code, @Param("indexEvt") String indexEvt); + + void updateType(@Param("code") Integer code, @Param("indexEvt") String indexEvt); + } diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/PqDeviceMapper.java b/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/PqDeviceMapper.java index 14c9324..1b18788 100644 --- a/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/PqDeviceMapper.java +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/PqDeviceMapper.java @@ -4,6 +4,7 @@ import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.njcn.influx.bo.po.PqDevice; import com.njcn.influx.bo.po.PqDeviceBak; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,4 +17,6 @@ import com.njcn.influx.bo.po.PqDeviceBak; @DS("master") public interface PqDeviceMapper extends BaseMapper { + PqDevice selectByLineId(@Param("lineId") String lineId); + } diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/PqsEventLogMapper.java b/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/PqsEventLogMapper.java new file mode 100644 index 0000000..87dddd3 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/PqsEventLogMapper.java @@ -0,0 +1,16 @@ +package com.njcn.influx.mapper; + + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.njcn.influx.bo.po.PqsEventLog; + +/** + * Description: + * Date: 2026/04/20 上午 10:21【需求编号】 + * + * @author clam + * @version V1.0.0 + */ +public interface PqsEventLogMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/mapping/OracleRmpEventDetailPOMapper.xml b/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/mapping/OracleRmpEventDetailPOMapper.xml index 6902932..3fcc2d0 100644 --- a/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/mapping/OracleRmpEventDetailPOMapper.xml +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/mapping/OracleRmpEventDetailPOMapper.xml @@ -37,4 +37,22 @@ + + + update pqs_eventdetail set eventreason = (select + a.dic_index from pqs_dicdata a,pqs_dictype b where b.dictype_name = + '暂降原因' and a.dic_type = b.dictype_index and a.triphase = #{code} and + a.state = 1 and b.state = 1) + where + eventdetail_index = #{indexEvt} + + + update pqs_eventdetail set EVENTTYPE = (select + a.dic_index from pqs_dicdata a,pqs_dictype b where b.dictype_name = + '暂降类型' and a.dic_type = b.dictype_index and a.triphase = #{code} and + a.state = 1 and b.state = 1) + where + eventdetail_index = #{indexEvt} + + diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/mapping/PqDeviceMapper.xml b/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/mapping/PqDeviceMapper.xml new file mode 100644 index 0000000..c9f6b47 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/mapping/PqDeviceMapper.xml @@ -0,0 +1,15 @@ + + + + + + + DEV_INDEX, GD_INDEX, SUB_INDEX, "NAME", "STATUS", DEVTYPE, LOGONTIME, UPDATETIME, + NODE_INDEX, PORTID, DEVFLAG, DEV_SERIES, DEV_KEY, IP, DEVMODEL, CALLFLAG, DATATYPE + + + + + \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/mapping/PqsEventLogMapper.xml b/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/mapping/PqsEventLogMapper.xml new file mode 100644 index 0000000..9826796 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/mapper/mapping/PqsEventLogMapper.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + ID, EVENTDETAIL_INDEX, fileupFlag, dealFlag, CreatTime, UpdateTime, REMARK + + \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/service/OracleEventDetailToMysqlService.java b/influx-data/influx-source/src/main/java/com/njcn/influx/service/OracleEventDetailToMysqlService.java index fda22d0..772f120 100644 --- a/influx-data/influx-source/src/main/java/com/njcn/influx/service/OracleEventDetailToMysqlService.java +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/service/OracleEventDetailToMysqlService.java @@ -14,4 +14,5 @@ import java.time.LocalDateTime; public interface OracleEventDetailToMysqlService extends IService { void eventBatch(LocalDateTime start, LocalDateTime end); + } diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/service/OracleToMysqlService.java b/influx-data/influx-source/src/main/java/com/njcn/influx/service/OracleToMysqlService.java new file mode 100644 index 0000000..55ef26d --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/service/OracleToMysqlService.java @@ -0,0 +1,16 @@ +package com.njcn.influx.service; + +import java.time.LocalDateTime; + +/** + * Description: + * Date: 2026/04/20 上午 9:53【需求编号】 + * + * @author clam + * @version V1.0.0 + */ +public interface OracleToMysqlService { + + void OracleToMySqlJob(LocalDateTime result, LocalDateTime modifiedResult); + void retryAndCleanEvery10Min(); +} diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/service/PqsEventLogService.java b/influx-data/influx-source/src/main/java/com/njcn/influx/service/PqsEventLogService.java new file mode 100644 index 0000000..0508654 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/service/PqsEventLogService.java @@ -0,0 +1,17 @@ +package com.njcn.influx.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.njcn.influx.bo.po.PqsEventLog; + +/** + *

+ * 服务类 + *

+ * + * @author wr + * @since 2024-03-05 + */ + +public interface PqsEventLogService extends IService { + +} diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/service/RmpEventDetailService.java b/influx-data/influx-source/src/main/java/com/njcn/influx/service/RmpEventDetailService.java new file mode 100644 index 0000000..1c81ace --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/service/RmpEventDetailService.java @@ -0,0 +1,15 @@ +package com.njcn.influx.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.njcn.influx.bo.po.RmpEventDetailPO; + +/** + * Description: + * Date: 2026/04/20 上午 11:28【需求编号】 + * + * @author clam + * @version V1.0.0 + */ +public interface RmpEventDetailService extends IService { + void syncToMysql(String eventId); +} diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/service/impl/EventAsyncService.java b/influx-data/influx-source/src/main/java/com/njcn/influx/service/impl/EventAsyncService.java new file mode 100644 index 0000000..8f4da64 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/service/impl/EventAsyncService.java @@ -0,0 +1,244 @@ +package com.njcn.influx.service.impl; + +import com.jcraft.jsch.ChannelSftp; + +import com.njcn.influx.bo.po.OracleRmpEventDetailPO; +import com.njcn.influx.bo.po.PqDevice; +import com.njcn.influx.bo.po.PqsEventLog; +import com.njcn.influx.component.WaveFileComponent; +import com.njcn.influx.component.dto.WaveDataDTO; +import com.njcn.influx.config.OtherConfig; +import com.njcn.influx.config.TargetConfig; +import com.njcn.influx.event.cause.jna.QvvrCauseDLL; +import com.njcn.influx.event.cause.model.DataFeature; +import com.njcn.influx.event.cause.model.EventAnalysisDTO; +import com.njcn.influx.event.type.jna.QvvrDLL; +import com.njcn.influx.mapper.OracleRmpEventDetailPOMapper; +import com.njcn.influx.mapper.PqDeviceMapper; +import com.njcn.influx.service.PqsEventLogService; +import com.njcn.influx.service.RmpEventDetailService; +import com.njcn.influx.sftp.SftpClient; +import com.sun.jna.Memory; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.io.*; +import java.nio.file.Files; +import java.util.Date; +import java.util.List; +import java.util.Objects; + + +@Service +@Slf4j +@RequiredArgsConstructor +public class EventAsyncService { + + + + + private final RmpEventDetailService rmpEventDetailService; + + private final PqDeviceMapper pqDeviceMapper; + private final WaveFileComponent waveFileComponent; + + private final OtherConfig config; + + private final TargetConfig targetConfig; + + private final OracleRmpEventDetailPOMapper oracleRmpEventDetailPOMapper; + private final PqsEventLogService pqsEventLogService; + + @Value("${business.dealFlag:true}") + private Boolean dealFlag; + @Value("${business.upLoadFlag:true}") + private Boolean upLoadFlag; + + + // ============================ + // 文件同步 + 高级算法 + // ============================ +// @Async("eventTaskExecutor") + public void asyncHandleEvent(OracleRmpEventDetailPO detail ) { + try { + log.info("异步处理事件:{} 文件:{}", detail.getEventId(), detail.getWavePath()); + // ========== 1. 查看波形文件是否存在 ========== + PqDevice pqDevice = pqDeviceMapper.selectByLineId(detail.getMeasurementPointId()); + String wavePath = config.getWavePath(); + String cfgPath = wavePath + File.separator + pqDevice.getIp() + File.separator + detail.getWavePath() + ".CFG" ; + String datPath = wavePath + File.separator + pqDevice.getIp() + File.separator + detail.getWavePath() + ".DAT" ; + + + log.info("本地磁盘波形文件路径----" + cfgPath); + InputStream cfgStream = getFileInputStreamByFilePath(cfgPath); + InputStream datStream = getFileInputStreamByFilePath(datPath); + + if((Objects.nonNull(cfgStream)&&Objects.nonNull(datStream))){ + // ========== 2. 高级算法更新原因/类型 ========== + if(dealFlag){ + EventAnalysisDTO eventAnalysisDTO = null; + try { + eventAnalysisDTO = advancedAlgorithm(cfgStream, datStream); + log.info("暂降原因:"+eventAnalysisDTO.getCause()+"----暂降类型:"+eventAnalysisDTO.getType()); + oracleRmpEventDetailPOMapper.updateCause(eventAnalysisDTO.getCause(),detail.getEventId()); + oracleRmpEventDetailPOMapper.updateType(eventAnalysisDTO.getType(),detail.getEventId()); + pqsEventLogService.lambdaUpdate().set(PqsEventLog::getDealflag,1).set(PqsEventLog::getUpdatetime,new Date()).eq(PqsEventLog::getEventdetailIndex,detail.getEventId()).update(); + } catch (Exception e) { + pqsEventLogService.lambdaUpdate().set(PqsEventLog::getRemark,e.getMessage().length()>50?e.getMessage().substring(50):e.getMessage()).set(PqsEventLog::getUpdatetime,new Date()).eq(PqsEventLog::getEventdetailIndex,detail.getEventId()).update(); + + } + + } + if(upLoadFlag){ + // ========== 4. SFTP文件同步 ========== + try { + syncFileToSftp(pqDevice.getIp(), detail.getWavePath(), cfgPath, datPath); + pqsEventLogService.lambdaUpdate().set(PqsEventLog::getFileupflag,1).set(PqsEventLog::getUpdatetime,new Date()).eq(PqsEventLog::getEventdetailIndex,detail.getEventId()).update(); + + } catch (Exception e) { + pqsEventLogService.lambdaUpdate().set(PqsEventLog::getRemark,e.getMessage().length()>50?e.getMessage().substring(50):e.getMessage()).set(PqsEventLog::getUpdatetime,new Date()).eq(PqsEventLog::getEventdetailIndex,detail.getEventId()).update(); + + } + + } + + rmpEventDetailService.syncToMysql(detail.getEventId()); + + } + + } catch (Exception e) { + log.error("异步处理失败 eventId:{}", detail.getEventId(), e); + } + + } + + // ================== + // 已修复:SFTP上传(无reset,无mark异常) + // ================== + private void syncFileToSftp(String deviceIp, String wavePath, String cfgFilePath, String datFilePath) throws Exception { + try (SftpClient client = new SftpClient() ) { + client.connect(targetConfig); + ChannelSftp channel = client.getChannel(); + + String remoteDir = targetConfig.getBasePath() + "/" + deviceIp; + client.createRemoteDirectory(remoteDir); + + String remoteCfg = remoteDir + "/" + wavePath + ".CFG"; + String remoteDat = remoteDir + "/" + wavePath + ".DAT"; + + channel.put(new FileInputStream(cfgFilePath), remoteCfg); + channel.put(new FileInputStream(datFilePath), remoteDat); + log.info("SFTP上传成功:{}", remoteCfg); + + } catch (Exception e) { + log.error("SFTP上传失败", e); + throw new Exception("SFTP上传失败:"+(e.getMessage().length()>50?e.getMessage().substring(50):e.getMessage())); + } + } + + + // ================== + // 高级算法:更新 EVENTREASON / EVENTTYPE + // ================== + private EventAnalysisDTO advancedAlgorithm(InputStream cfgStream , InputStream datStream) throws Exception { + EventAnalysisDTO eventAnalysis = new EventAnalysisDTO(); + log.info("执行高级算法:{}"); + WaveDataDTO waveDataDTO = waveFileComponent.getComtradeNoAddPoints(cfgStream, datStream, 0); + + List> listWaveData = waveDataDTO.getListWaveData(); + // 暂降类型 + // 创建数据结构 + QvvrDLL.QvvrDataStruct typeDataStruct = new QvvrDLL.QvvrDataStruct(); + System.out.println("初始化qvvrdll成功-----------"); + typeDataStruct.smp_rate = waveDataDTO.getComtradeCfgDTO().getFinalSampleRate(); + System.out.println("采样率-----------" + typeDataStruct.smp_rate); + typeDataStruct.smp_len = listWaveData.size(); + System.out.println("波形长度-----------" + listWaveData.size()); + + // 获取ABC三相的瞬时数据 + for (int i = 0; i < listWaveData.size(); i++) { + typeDataStruct.smp_va[i] = listWaveData.get(i).get(1); + typeDataStruct.smp_vb[i] = listWaveData.get(i).get(2); + typeDataStruct.smp_vc[i] = listWaveData.get(i).get(3); + } + + + // 执行算法分析 - 直接调用C DLL + try { + QvvrDLL.INSTANCE.qvvr_fun(typeDataStruct); + + log.info("调用qvvrdll成功-----------"); + + if (typeDataStruct.evt_num > 0) { + // 全局比较找出最小三相电压特征值 + float globalMinVoltage = Float.MAX_VALUE; + int globalFaultType = 10; + for (int i = 0; i < typeDataStruct.evt_num; i++) { + QvvrDLL.EventBuffer evt = typeDataStruct.evt_buf[i]; + for (int j = 0; j < evt.u_min_num; j++) { + float u3min = evt.u3_min[j]; + if (u3min < globalMinVoltage) { + globalMinVoltage = u3min; + globalFaultType = evt.qvvr_cata_type[j]; + } + } + } + eventAnalysis.setType(globalFaultType); + } else { + eventAnalysis.setType(DataFeature.TYPE10); + } + System.out.println("结束qvvrdll方法调用-----------"); + } catch (Exception e) { + eventAnalysis.setType(DataFeature.TYPE10); + eventAnalysis.setTypeFlag(0); + } + + + // 暂降原因JNA的方式 + QvvrCauseDLL.QvvrDataStruct causeDataStruct = new QvvrCauseDLL.QvvrDataStruct(); + causeDataStruct.smp_rate = waveDataDTO.getComtradeCfgDTO().getFinalSampleRate(); + causeDataStruct.smp_len = listWaveData.size(); + // 获取ABC三相的瞬时数据 + for (int i = 0; i < listWaveData.size(); i++) { + causeDataStruct.smp_va[i] = listWaveData.get(i).get(1); + causeDataStruct.smp_vb[i] = listWaveData.get(i).get(2); + causeDataStruct.smp_vc[i] = listWaveData.get(i).get(3); + } + // 执行算法分析 - 直接调用C DLL + try { + QvvrCauseDLL.INSTANCE.qvvr_fun_cause(causeDataStruct); + eventAnalysis.setCause(causeDataStruct.cause); + if (causeDataStruct.no_cal != 0) { + eventAnalysis.setCauseFlag(0); + } + } catch (Exception e) { + eventAnalysis.setCause(DataFeature.CAUSE_TYPE0); + eventAnalysis.setCauseFlag(0); + } + System.out.println("暂降原因分析完毕==============="); + System.out.println("cause:" + eventAnalysis); + return eventAnalysis; + } + + 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) { + return null; + } + return inputStream; + } catch (IOException e) { + return null; + } + } else { + return null; + } + } +} \ No newline at end of file diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/service/impl/OracleToMysqlServiceImpl.java b/influx-data/influx-source/src/main/java/com/njcn/influx/service/impl/OracleToMysqlServiceImpl.java new file mode 100644 index 0000000..ac07ce3 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/service/impl/OracleToMysqlServiceImpl.java @@ -0,0 +1,147 @@ +package com.njcn.influx.service.impl; + +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.njcn.influx.bo.po.*; +import com.njcn.influx.mapper.OracleRmpEventDetailPOMapper; +import com.njcn.influx.mapper.PqDeviceMapper; +import com.njcn.influx.mapper.RmpEventDetailPOMapper; +import com.njcn.influx.service.OracleToMysqlService; +import com.njcn.influx.service.PqLineBakService; +import com.njcn.influx.service.PqsEventLogService; +import com.njcn.influx.service.RmpEventDetailService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.jdbc.core.BeanPropertyRowMapper; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.nio.file.Files; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.*; +import java.util.stream.Collectors; + +/** + * Description: + * Date: 2026/04/20 上午 9:54【需求编号】 + * + * @author clam + * @version V1.0.0 + */ +@RequiredArgsConstructor +@Service +@Slf4j +public class OracleToMysqlServiceImpl implements OracleToMysqlService { + + private final RmpEventDetailService rmpEventDetailService; + private final OracleRmpEventDetailPOMapper oracleRmpEventDetailPOMapper; + + + private final PqsEventLogService pqsEventLogService; + private final EventAsyncService eventAsyncService; + @Value("${business.dealFlag:true}") + private Boolean dealFlag; + @Value("${business.upLoadFlag:true}") + private Boolean upLoadFlag; + @Override + public void OracleToMySqlJob(LocalDateTime start, LocalDateTime end) { + log.info("===== 定时扫描事件开始 ====="); + + List oracleRmpEventDetailPOList = oracleRmpEventDetailPOMapper.selectList(new LambdaQueryWrapper().between(OracleRmpEventDetailPO::getCreateTime,start,end)); + for (OracleRmpEventDetailPO detail : oracleRmpEventDetailPOList) { + String eventId = detail.getEventId(); + + // 2. 判断是否已存在日志,避免重复 + Integer cnt = pqsEventLogService.lambdaQuery().eq(PqsEventLog::getEventdetailIndex,eventId).count(); + + if (cnt == null ||cnt < 1){ + // 3. 初始化日志:0未上传 0未计算 + PqsEventLog pqsEventLog = new PqsEventLog(); + pqsEventLog.setId(UUID.randomUUID().toString()); + pqsEventLog.setEventdetailIndex(eventId); + //判断是否配置数据同步或者高级算法功能 + if(dealFlag){ + pqsEventLog.setDealflag(0); + }else { + pqsEventLog.setDealflag(2); + } + if(dealFlag){ + pqsEventLog.setFileupflag(0); + }else { + pqsEventLog.setFileupflag(2); + } + + pqsEventLog.setFileupflag(0); + pqsEventLog.setCreattime(new Date()); + pqsEventLog.setUpdatetime(new Date()); + pqsEventLogService.save(pqsEventLog); + + String wavename = detail.getWavePath(); + + rmpEventDetailService.syncToMysql(eventId); + + // ============================ + // WAVENAME 为空:直接标记 + // ============================ + if (wavename == null || wavename.trim().isEmpty()) { + + continue; + } + + // ============================ + // WAVENAME 非空:线程池异步处理 + // ============================ + eventAsyncService.asyncHandleEvent(detail); + } + + + } + } + + @Override + public void retryAndCleanEvery10Min() { + log.info("===== 10分钟重试补偿 + 过期清理 ====="); + + // 1. 扫描未处理:fileup=0 deal=0 + List todoList = pqsEventLogService.lambdaQuery().eq(PqsEventLog::getFileupflag, 0) + .or() + .eq(PqsEventLog::getDealflag, 0).list(); + + for (PqsEventLog log : todoList) { + String eventId = log.getEventdetailIndex(); + Date createTime = log.getCreattime(); + OracleRmpEventDetailPO oracleRmpEventDetailPO = oracleRmpEventDetailPOMapper.selectById(eventId); + // 查询最新WAVENAME + + + boolean isWaveEmpty = (oracleRmpEventDetailPO.getWavePath() == null || oracleRmpEventDetailPO.getWavePath().isEmpty()); + + // ====================== + // 超过2天:置为2 + // ====================== + if (createTime != null && System.currentTimeMillis() - createTime.getTime() > 2 * 86400000L) { + if (isWaveEmpty) { + pqsEventLogService.lambdaUpdate().set(PqsEventLog::getDealflag,2).set(PqsEventLog::getFileupflag,2).set(PqsEventLog::getUpdatetime,new Date()).eq(PqsEventLog::getEventdetailIndex,eventId); + continue; + } + } + + // ====================== + // 有文件:重试异步处理 + // ====================== + if (!isWaveEmpty) { + eventAsyncService.asyncHandleEvent(oracleRmpEventDetailPO); + } + } + + } + +} diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/service/impl/PqsEventLogServiceImpl.java b/influx-data/influx-source/src/main/java/com/njcn/influx/service/impl/PqsEventLogServiceImpl.java new file mode 100644 index 0000000..222aecc --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/service/impl/PqsEventLogServiceImpl.java @@ -0,0 +1,21 @@ +package com.njcn.influx.service.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +import com.njcn.influx.service.PqsEventLogService; +import com.njcn.influx.bo.po.PqsEventLog; +import com.njcn.influx.mapper.PqsEventLogMapper; +import org.springframework.stereotype.Service; + +/** + * Description: + * Date: 2026/04/20 上午 10:23【需求编号】 + * + * @author clam + * @version V1.0.0 + */ +@Service +@DS("master") +public class PqsEventLogServiceImpl extends ServiceImpl implements PqsEventLogService { +} diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/service/impl/RmpEventDetailServiceImpl.java b/influx-data/influx-source/src/main/java/com/njcn/influx/service/impl/RmpEventDetailServiceImpl.java new file mode 100644 index 0000000..7568396 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/service/impl/RmpEventDetailServiceImpl.java @@ -0,0 +1,142 @@ +package com.njcn.influx.service.impl; + +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.njcn.influx.bo.po.DictData; +import com.njcn.influx.bo.po.OracleRmpEventDetailPO; +import com.njcn.influx.bo.po.PqLineBak; +import com.njcn.influx.bo.po.RmpEventDetailPO; +import com.njcn.influx.mapper.OracleRmpEventDetailPOMapper; +import com.njcn.influx.mapper.RmpEventDetailPOMapper; +import com.njcn.influx.service.PqLineBakService; +import com.njcn.influx.service.RmpEventDetailService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * Description: + * Date: 2026/04/20 上午 11:29【需求编号】 + * + * @author clam + * @version V1.0.0 + */ +@Service +@RequiredArgsConstructor +public class RmpEventDetailServiceImpl extends ServiceImpl implements RmpEventDetailService { + private final OracleRmpEventDetailPOMapper oracleRmpEventDetailPOMapper; + private final PqLineBakService pqLineBakService; + + @Override + public void syncToMysql(String eventId) { + OracleRmpEventDetailPO oracleDetail = oracleRmpEventDetailPOMapper.selectById(eventId); + + List list = pqLineBakService.list(); + + //lineId:Oracle监测点ID id:Mysql监测点ID + Map oracleRelationMysql = list.stream().collect(Collectors.toMap(PqLineBak::getLineId, PqLineBak::getId)); + //获取Oracle字典 暂降类型:12 暂降原因:13 + List oracleReason= oracleRmpEventDetailPOMapper.selectByDicCodeList("暂降原因"); + List oracleType= oracleRmpEventDetailPOMapper.selectByDicCodeList("暂降类型"); + //获取Mysql字典 + List eventType = this.getBaseMapper().selectByDicCodeList("Event_Statis"); + List mysqlReason = this.getBaseMapper().selectByDicCodeList("Event_Reason"); + List mysqlType = this.getBaseMapper().selectByDicCodeList("Event_Type"); + //字典类型 + Map mapReason = getRelationList(oracleReason, mysqlReason); + Map mapType = getRelationList(oracleType, mysqlType); + + if(oracleRelationMysql.containsKey(oracleDetail.getMeasurementPointId())){ + String mysqlLineID = oracleRelationMysql.get(oracleDetail.getMeasurementPointId()); + RmpEventDetailPO po=new RmpEventDetailPO(); + po.setEventId(eventId); + po.setMeasurementPointId(mysqlLineID); + po.setEventType(eventTypeId(oracleDetail.getEventType(),eventType)); + po.setAdvanceReason(getDicId(oracleDetail.getAdvanceReason(),mapReason)); + po.setAdvanceType(getDicId(oracleDetail.getAdvanceType(),mapType)); + po.setEventassIndex(oracleDetail.getEventassIndex()); + po.setDqTime(oracleDetail.getDqTime()); + po.setDealTime(oracleDetail.getDealTime()); + po.setNum(oracleDetail.getNum()); + po.setFileFlag(oracleDetail.getFileFlag()); + po.setDealFlag(oracleDetail.getDealFlag()); + + if(Objects.nonNull(oracleDetail.getFirstTime())) { + po.setFirstTime(oracleDetail.getFirstTime().plus(oracleDetail.getFirstMs().intValue(), ChronoUnit.MILLIS)); + } + po.setFirstType(oracleDetail.getFirstType()); + po.setFirstMs(oracleDetail.getFirstMs()); + po.setEnergy(oracleDetail.getEnergy()); + po.setSeverity(oracleDetail.getSeverity()); + po.setSagsource(oracleDetail.getSagsource()); + LocalDateTime startTime = oracleDetail.getStartTime(); + LocalDateTime time = startTime.plus(oracleDetail.getMs(), ChronoUnit.MILLIS); + po.setStartTime(time); + po.setDuration(oracleDetail.getDuration().divide(BigDecimal.valueOf(1000))); + po.setFeatureAmplitude(oracleDetail.getFeatureAmplitude()); + po.setPhase(oracleDetail.getPhase()); + po.setEventDescribe(oracleDetail.getEventDescribe()); + po.setWavePath(oracleDetail.getWavePath()); + po.setTransientValue(oracleDetail.getTransientValue()); + this.saveOrUpdate(po); + } + } + + //获取暂降类型id + private String eventTypeId(String eventType, List eventTypeList){ + String code=""; + //事件类型(0:扰动,1:暂降,2:暂升,3:中断,4:其他,5:录波) + if("0".equals(eventType)){ + code="Disturbance"; + } + if("1".equals(eventType)){ + code="Voltage_Dip"; + } + if("2".equals(eventType)){ + code="Voltage_Rise"; + } + if("3".equals(eventType)){ + code="Short_Interruptions"; + } + if("4".equals(eventType)){ + code="Other"; + } + if("5".equals(eventType)){ + code="Recording_Wave"; + } + String finalCode = code; + DictData dictData = eventTypeList.stream().filter(x -> finalCode.equals(x.getCode())).findFirst().get(); + if(ObjectUtil.isNotNull(dictData)){ + return dictData.getId(); + } + return ""; + } + + //类型匹配 + private Map getRelationList(List oracleReason,List mysqlReason){ + Map map=new HashMap<>(); + for (DictData dictData : oracleReason) { + for (DictData data : mysqlReason) { + if(dictData.getAlgoDescribe().equals(data.getAlgoDescribe())){ + map.put(dictData.getId(),data.getId()); + } + } + } + return map; + } + + private String getDicId(String dicReason,Map map){ + if(map.containsKey(dicReason)){ + return map.get(dicReason); + } + return ""; + } +} diff --git a/influx-data/influx-source/src/main/java/com/njcn/influx/sftp/SftpClient.java b/influx-data/influx-source/src/main/java/com/njcn/influx/sftp/SftpClient.java new file mode 100644 index 0000000..053f038 --- /dev/null +++ b/influx-data/influx-source/src/main/java/com/njcn/influx/sftp/SftpClient.java @@ -0,0 +1,126 @@ +package com.njcn.influx.sftp; + +import com.jcraft.jsch.ChannelSftp; +import com.jcraft.jsch.*; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.SftpException; +import com.njcn.influx.config.TargetConfig; +import lombok.Data; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.util.Vector; + +/** + * Description: + * Date: 2025/10/16 下午 3:00【需求编号】 + *SFTP客户端实现 + * @author clam + * @version V1.0.0 + */ +@Service +@Data +public class SftpClient implements AutoCloseable{ + private static final Logger logger = LoggerFactory.getLogger(SftpClient.class); + + private JSch jsch; + private Session session; + private ChannelSftp channel; + + public void connect(TargetConfig config) throws JSchException { + jsch = new JSch(); + + // 设置私钥(如果提供) + if (config.getPrivateKeyPath() != null && !config.getPrivateKeyPath().isEmpty()) { + jsch.addIdentity(config.getPrivateKeyPath()); + } + + session = jsch.getSession(config.getUsername(), config.getHost(), config.getPort()); + + // 设置密码(如果提供) + if (config.getPassword() != null && !config.getPassword().isEmpty()) { + session.setPassword(config.getPassword()); + } + + // 配置SSH连接 + java.util.Properties sshConfig = new java.util.Properties(); + sshConfig.put("StrictHostKeyChecking", "no"); + session.setConfig(sshConfig); + + session.connect(30000); // 30秒超时 + + // 打开SFTP通道 + channel = (ChannelSftp) session.openChannel("sftp"); + channel.connect(30000); + } + public void uploadFile(String localFile, String remotePath) throws SftpException { + File file = new File(localFile); + String remoteFile = ensureRemotePath(remotePath, file.getName()); + + // 确保远程目录存在 + createRemoteDirectory(remotePath); + + // 上传文件 + channel.put(localFile, remoteFile); + } + + public ChannelSftp.LsEntry getRemoteFileInfo(String remotePath) throws SftpException { + @SuppressWarnings("unchecked") + Vector files = channel.ls(remotePath); + if (files != null && !files.isEmpty()) { + return files.get(0); + } + return null; + } + + private String ensureRemotePath(String remotePath, String fileName) { + if (remotePath.endsWith("/")) { + return remotePath + fileName; + } else { + return remotePath + "/" + fileName; + } + } + + public void createRemoteDirectory(String remotePath) throws SftpException { + + // 处理Windows路径分隔符 + String normalizedPath = remotePath.replace("\\", "/"); + // 去掉开头的/(避免根目录重复创建) + if (normalizedPath.startsWith("/")) { + normalizedPath = normalizedPath.substring(1); + } + String[] directories = normalizedPath.split("/"); + StringBuilder currentPath = new StringBuilder(); + + // 递归创建多层目录 + for (String dir : directories) { + if (dir.isEmpty()) { + continue; + } + currentPath.append("/").append(dir); + try { + channel.mkdir(currentPath.toString()); + logger.debug("创建远程目录成功: {}", currentPath); + } catch (SftpException e) { + if (e.id != ChannelSftp.SSH_FX_FAILURE) { + logger.error("创建远程目录失败: {}", currentPath, e); + throw e; + } else { + logger.debug("远程目录已存在: {}", currentPath); + } + } + } + } + + @Override + public void close() { + if (channel != null) { + channel.disconnect(); + } + if (session != null) { + session.disconnect(); + } + } +} diff --git a/influx-data/influx-target/pom.xml b/influx-data/influx-target/pom.xml index 70a6e63..066f923 100644 --- a/influx-data/influx-target/pom.xml +++ b/influx-data/influx-target/pom.xml @@ -50,6 +50,37 @@ influx-target + + + src/main/resources + true + + *.yml + + + + src/main/resources + false + + *.dll + *.xlsx + + + + src/main/resources + false + + *.so + + + + src/main/java + false + + **/*.xml + + + org.springframework.boot diff --git a/influx-data/influx-target/src/main/java/com/njcn/influx/controller/OracleToInfluxDBController.java b/influx-data/influx-target/src/main/java/com/njcn/influx/controller/OracleToInfluxDBController.java index e972a88..6f57206 100644 --- a/influx-data/influx-target/src/main/java/com/njcn/influx/controller/OracleToInfluxDBController.java +++ b/influx-data/influx-target/src/main/java/com/njcn/influx/controller/OracleToInfluxDBController.java @@ -3,10 +3,7 @@ package com.njcn.influx.controller; import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.util.StrUtil; -import com.njcn.influx.service.OracleEventDetailToMysqlService; -import com.njcn.influx.service.OracleMonitorStatusToMysqlService; -import com.njcn.influx.service.OracleToInfluxDBService; -import com.njcn.influx.service.PqsOnlineratePOService; +import com.njcn.influx.service.*; import com.njcn.oracle.bo.param.DataAsynParam; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; @@ -44,6 +41,7 @@ public class OracleToInfluxDBController { private final OracleEventDetailToMysqlService oracleEventDetailToMysqlService; private final OracleMonitorStatusToMysqlService oracleMonitorStatusToMysqlService; + private final OracleToMysqlService oracleToMysqlService; @PostMapping("/dataSync") @ApiOperation("数据同步") @@ -119,6 +117,20 @@ public class OracleToInfluxDBController { } return true; } + + @GetMapping("/eventRecall") + @ApiOperation("eventDetail表数据同步补招接口") + public Boolean eventRecall(@RequestParam("startDateTime") String startDateTime,@RequestParam("endDateTime") String endDateTime) { + try { + LocalDateTime startDate = LocalDateTimeUtil.beginOfDay(LocalDateTimeUtil.parse(startDateTime, DatePattern.NORM_DATETIME_PATTERN)); + LocalDateTime endDate = LocalDateTimeUtil.endOfDay(LocalDateTimeUtil.parse(endDateTime, DatePattern.NORM_DATETIME_PATTERN)); + oracleToMysqlService.OracleToMySqlJob(startDate, endDate ); + + } catch (Exception exception) { + exception.printStackTrace(); + } + return true; + } @GetMapping("/mSync") @ApiOperation("监测点信息同步") public Boolean monitorTimeSync() { diff --git a/influx-data/influx-target/src/main/java/com/njcn/influx/job/OracleToInfluxDBJob.java b/influx-data/influx-target/src/main/java/com/njcn/influx/job/OracleToInfluxDBJob.java index 97b65d1..ebd4a0c 100644 --- a/influx-data/influx-target/src/main/java/com/njcn/influx/job/OracleToInfluxDBJob.java +++ b/influx-data/influx-target/src/main/java/com/njcn/influx/job/OracleToInfluxDBJob.java @@ -1,123 +1,125 @@ -package com.njcn.influx.job; - -import com.njcn.influx.bo.param.TableEnum; -import com.njcn.influx.service.OracleEventDetailToMysqlService; -import com.njcn.influx.service.OracleMonitorStatusToMysqlService; -import com.njcn.influx.service.OracleToInfluxDBService; -import com.njcn.influx.service.PqsOnlineratePOService; -import com.njcn.oracle.bo.param.DataAsynParam; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.temporal.ChronoUnit; - -/** - * Description: - * Date: 2024/1/18 10:15【需求编号】 - * - * @author clam - * @version V1.0.0 - */ -@Component -@EnableScheduling -@RequiredArgsConstructor -@Slf4j -public class OracleToInfluxDBJob { - - - private final OracleToInfluxDBService oracleToInfluxDBService; - - private final OracleEventDetailToMysqlService oracleEventDetailToMysqlService; - private final OracleMonitorStatusToMysqlService oracleMonitorStatusToMysqlService; - - private final PqsOnlineratePOService pqsOnlineratePOService; - /*@Scheduled(cron="0 5 0 * * ?") - public void execute() { - DataAsynParam dataAsynParam = new DataAsynParam(); - dataAsynParam.setStartTime(LocalDate.now().plusDays(-1)); - dataAsynParam.setEndTime(LocalDate.now().plusDays(-1)); - dataAsynParam.setTableNames(TableEnum.getExecutableTypes()); - dataAsynParam.setExcuteType(2); - oracleToInfluxDBService.dataBacthSysc(dataAsynParam); - }*/ - - //每小时03分钟时执行上一个小时的数据同步 - //河北这边比较特殊, - @Scheduled(cron="0 15 * * * ?") - public void executeHours() { - DataAsynParam dataAsynParam = new DataAsynParam(); - // 获取当前时间 - LocalDateTime now = LocalDateTime.now(); - - // 减去一个小时 - LocalDateTime oneHourAgo = now.minusHours(2); - - // 将分钟和秒设置为0 - LocalDateTime result = oneHourAgo.truncatedTo(ChronoUnit.HOURS); - // 加上59分钟59秒 - LocalDateTime modifiedResult = result.plusMinutes(59).plusSeconds(59); - dataAsynParam.setStartDateTime(result); - dataAsynParam.setEndDateTime(modifiedResult); - dataAsynParam.setTableNames(TableEnum.getExecutableTypes()); - dataAsynParam.setExcuteType(2); - oracleToInfluxDBService.hourseDataBacthSysc(dataAsynParam); - } - //每10分钟执行一次pqOnlinerate表同步 - @Scheduled(cron="0 0/10 * * * ?") - public void pqOnlinerate() { - DataAsynParam dataAsynParam = new DataAsynParam(); - // 获取当前时间 - LocalDateTime now = LocalDateTime.now(); - dataAsynParam.setStartDateTime(now); - pqsOnlineratePOService.minutesDataBacthSysc(dataAsynParam); - } - - /** - * 每小时同步oracle数据库暂态事件 - * @date 2024/3/5 - */ - @Scheduled(cron="0 0/10 * * * ?") - public void executeEvent() { - // 获取当前时间 - LocalDateTime now = LocalDateTime.now(); - // 减去一个小时 - LocalDateTime oneHourAgo = now.minusHours(1); - // 将分钟和秒设置为0 - LocalDateTime result = oneHourAgo.truncatedTo(ChronoUnit.HOURS); - // 加上59分钟59秒 - LocalDateTime modifiedResult = result.plusMinutes(59).plusSeconds(59); - oracleEventDetailToMysqlService.eventBatch(result,modifiedResult); - } - - /** - * 每天同步台账装置的运行状态,监测点的运行状态 - * @date 2024/3/5 - */ - @Scheduled(cron="0 0/10 * * * ?") - public void synLedgerRunFlag() { - oracleMonitorStatusToMysqlService.monitorStatusSync(); - } - - /** - * 每天同步台账装置的最后更新时间 - * @date 2024/3/5 - */ - @Scheduled(cron="0 45 0 * * ?") - public void synLedgerUpdateTime() { - oracleMonitorStatusToMysqlService.devUpdateTimeSync(); - } - - /** - * 每天同步台账监测点部分信息 仅数据中心使用 - * @date 2024/3/5 - */ - /* @Scheduled(cron="0 30 0 * * ?") - public void synLedgerMonitor() { - oracleMonitorStatusToMysqlService.monitorTimeSync(); - }*/ -} +//package com.njcn.influx.job; +// +//import com.njcn.influx.bo.param.TableEnum; +//import com.njcn.influx.service.OracleEventDetailToMysqlService; +//import com.njcn.influx.service.OracleMonitorStatusToMysqlService; +//import com.njcn.influx.service.OracleToInfluxDBService; +//import com.njcn.influx.service.PqsOnlineratePOService; +//import com.njcn.oracle.bo.param.DataAsynParam; +//import lombok.RequiredArgsConstructor; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.scheduling.annotation.EnableScheduling; +//import org.springframework.scheduling.annotation.Scheduled; +//import org.springframework.stereotype.Component; +// +//import java.time.LocalDate; +//import java.time.LocalDateTime; +//import java.time.temporal.ChronoUnit; +// +///** +// * Description: +// * Date: 2024/1/18 10:15【需求编号】 +// * +// * @author clam +// * @version V1.0.0 +// */ +//@Component +//@EnableScheduling +//@RequiredArgsConstructor +//@Slf4j +//public class OracleToInfluxDBJob { +// +// +// private final OracleToInfluxDBService oracleToInfluxDBService; +// +// private final OracleEventDetailToMysqlService oracleEventDetailToMysqlService; +// private final OracleMonitorStatusToMysqlService oracleMonitorStatusToMysqlService; +// +// private final PqsOnlineratePOService pqsOnlineratePOService; +// /*@Scheduled(cron="0 5 0 * * ?") +// public void execute() { +// DataAsynParam dataAsynParam = new DataAsynParam(); +// dataAsynParam.setStartTime(LocalDate.now().plusDays(-1)); +// dataAsynParam.setEndTime(LocalDate.now().plusDays(-1)); +// dataAsynParam.setTableNames(TableEnum.getExecutableTypes()); +// dataAsynParam.setExcuteType(2); +// oracleToInfluxDBService.dataBacthSysc(dataAsynParam); +// }*/ +// +// //每小时03分钟时执行上一个小时的数据同步 +// //河北这边比较特殊, +// @Scheduled(cron="0 15 * * * ?") +// public void executeHours() { +// DataAsynParam dataAsynParam = new DataAsynParam(); +// // 获取当前时间 +// LocalDateTime now = LocalDateTime.now(); +// +// // 减去一个小时 +// LocalDateTime oneHourAgo = now.minusHours(2); +// +// // 将分钟和秒设置为0 +// LocalDateTime result = oneHourAgo.truncatedTo(ChronoUnit.HOURS); +// // 加上59分钟59秒 +// LocalDateTime modifiedResult = result.plusMinutes(59).plusSeconds(59); +// dataAsynParam.setStartDateTime(result); +// dataAsynParam.setEndDateTime(modifiedResult); +// dataAsynParam.setTableNames(TableEnum.getExecutableTypes()); +// dataAsynParam.setExcuteType(2); +// oracleToInfluxDBService.hourseDataBacthSysc(dataAsynParam); +// } +// //每10分钟执行一次pqOnlinerate表同步 +//// @Scheduled(cron="0 0/10 * * * ?") +//// public void pqOnlinerate() { +//// DataAsynParam dataAsynParam = new DataAsynParam(); +//// // 获取当前时间 +//// LocalDateTime now = LocalDateTime.now(); +//// dataAsynParam.setStartDateTime(now); +//// pqsOnlineratePOService.minutesDataBacthSysc(dataAsynParam); +//// } +// +// /** +// * 每小时同步oracle数据库暂态事件 +// * @date 2024/3/5 +// */ +// @Scheduled(cron="0 0/10 * * * ?") +// public void executeEvent() { +// // 获取当前时间 +// LocalDateTime now = LocalDateTime.now(); +// // 减去一个小时 +// LocalDateTime oneHourAgo = now.minusHours(1); +// // 将分钟和秒设置为0 +// LocalDateTime result = oneHourAgo.truncatedTo(ChronoUnit.HOURS); +// // 加上59分钟59秒 +// LocalDateTime modifiedResult = result.plusMinutes(59).plusSeconds(59); +// oracleEventDetailToMysqlService.eventBatch(result,modifiedResult); +// } +// +// /** +// * 每天同步台账装置的运行状态,监测点的运行状态 +// * @date 2024/3/5 +// */ +// @Scheduled(cron="0 0/10 * * * ?") +// public void synLedgerRunFlag() { +// oracleMonitorStatusToMysqlService.monitorStatusSync(); +// } +// +// /** +// * 每天同步台账装置的最后更新时间 +// * @date 2024/3/5 +// */ +// @Scheduled(cron="0 45 0 * * ?") +// public void synLedgerUpdateTime() { +// oracleMonitorStatusToMysqlService.devUpdateTimeSync(); +// } +// +// /** +// * 每天同步台账监测点部分信息 仅数据中心使用 +// * @date 2024/3/5 +// */ +// /* @Scheduled(cron="0 30 0 * * ?") +// public void synLedgerMonitor() { +// oracleMonitorStatusToMysqlService.monitorTimeSync(); +// }*/ +//} +// +// diff --git a/influx-data/influx-target/src/main/java/com/njcn/influx/job/OracleToMySqlJob.java b/influx-data/influx-target/src/main/java/com/njcn/influx/job/OracleToMySqlJob.java new file mode 100644 index 0000000..a2bd60d --- /dev/null +++ b/influx-data/influx-target/src/main/java/com/njcn/influx/job/OracleToMySqlJob.java @@ -0,0 +1,50 @@ +package com.njcn.influx.job; + + +import com.njcn.influx.service.OracleToMysqlService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; + + +/** + * Description: + * Date: 2026/04/20 上午 9:44【需求编号】 + * + * @author clam + * @version V1.0.0 + */ +@Component +@EnableScheduling +@RequiredArgsConstructor +@Slf4j +public class OracleToMySqlJob { + + private final OracleToMysqlService oracleToMysqlService; + + + @Scheduled(cron = "${business.executeEventExpression}") + public void executeEvent() { + // 获取当前时间 + LocalDateTime now = LocalDateTime.now(); + // 减去一个小时 + LocalDateTime oneHourAgo = now.minusHours(3); + + oracleToMysqlService.OracleToMySqlJob(oneHourAgo,now); + } + + + // ============================== + // 每10分钟:重试 + 2天过期处理 + // ============================== + @Scheduled(cron = "${business.retryAndCleanEvery10Min}") + public void retryAndCleanEvery10Min() { + + oracleToMysqlService.retryAndCleanEvery10Min();; + } +} diff --git a/influx-data/influx-target/src/main/resources/application-bd.yml b/influx-data/influx-target/src/main/resources/application-bd.yml new file mode 100644 index 0000000..72a79af --- /dev/null +++ b/influx-data/influx-target/src/main/resources/application-bd.yml @@ -0,0 +1,130 @@ + +business: + #分片次数,一定为24的约数,1 2 3 4 6 8 12 24 + slice: 4 + # 0.pq 1.pms + type: 0 + #处理波形数据位置 + wavePath: D:\Comtrade + retryAndCleanEvery10Min: 0 */10 * * * ? + executeEventExpression: 0 */3 * * * ? +server: + port: 8093 + #springsecurity默认过期时间30m + servlet: + session: + timeout: 1440m + target: + host: 192.168.1.67 + port: 22 + username: root + password: 'dnzl@#001' + basePath: /home/hndnzl + privateKeyPath: + +spring: + security: + user: + name: data_njcn + password: dnzl@#002 + #influxDB内容配置 + influx: + url: http://192.168.1.103:18086 + user: admin + password: 123456 + database: pqsbase_wx + mapper-location: com.njcn.influx.imapper + application: + name: oracle-influx + autoconfigure: + exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure + datasource: + dynamic: + druid: + initial-size: 10 + # 初始化大小,最小,最大 + min-idle: 20 + maxActive: 500 + # 配置获取连接等待超时的时间 + maxWait: 60000 + # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 + timeBetweenEvictionRunsMillis: 60000 + # 配置一个连接在池中最小生存的时间,单位是毫秒 + minEvictableIdleTimeMillis: 300000 + testWhileIdle: true + testOnBorrow: true + validation-query: SELECT 1 from dual + testOnReturn: false + # 打开PSCache,并且指定每个连接上PSCache的大小 + poolPreparedStatements: true + maxPoolPreparedStatementPerConnectionSize: 20 + filters: stat,wall + filter: + wall: + config: + multi-statement-allow: true + none-base-statement-allow: true + enabled: true + # 配置DruidStatFilter + web-stat-filter: + enabled: true + url-pattern: "/*" + exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*" + # 配置DruidStatViewServlet + stat-view-servlet: + enabled: true + url-pattern: "/druid/*" + # IP白名单(没有配置或者为空,则允许所有访问) + allow: #127.0.0.1,192.168.163.1 + # IP黑名单 (存在共同时,deny优先于allow) + deny: #192.168.1.73 + # 禁用HTML页面上的“Reset All”功能 + reset-enable: false + # 登录名 + login-username: admin + # 登录密码 + login-password: njcnpqs + query-timeout: 36000 + primary: master + strict: false + datasource: + master: + url: jdbc:oracle:thin:@127.0.0.1:1521:pqsbase + username: pqsadmin + password: '@#001njcnpqs' + driver-class-name: oracle.jdbc.driver.OracleDriver + target: + url: jdbc:mysql://192.168.1.103:13307/pqsinfo_hn?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=CTT + username: root + password: njcnpqs + driver-class-name: com.mysql.cj.jdbc.Driver + redis: + database: 15 + host: 192.168.1.103 + port: 16379 + password: njcnpqs + timeout: 5000 + lettuce: + pool: + max-active: 8 + max-wait: -1 + max-idle: 8 + min-idle: 0 + #不做限制的参数配置 +#mybatis配置信息 +mybatis-plus: + #别名扫描 + type-aliases-package: com.njcn.oracle.bo + mapper-locations: classpath*:com/njcn/**/mapping/*.xml + configuration: + #驼峰命名 + map-underscore-to-camel-case: true + #配置sql日志输出 + # log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + #关闭日志输出 + log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl + global-config: + db-config: + #指定主键生成策略 + id-type: assign_uuid + diff --git a/influx-data/influx-target/src/main/resources/application-hn.yml b/influx-data/influx-target/src/main/resources/application-hn.yml new file mode 100644 index 0000000..16488df --- /dev/null +++ b/influx-data/influx-target/src/main/resources/application-hn.yml @@ -0,0 +1,130 @@ + +business: + #分片次数,一定为24的约数,1 2 3 4 6 8 12 24 + slice: 4 + # 0.pq 1.pms + type: 0 + #处理波形数据位置 + wavePath: F:\Comtrade + retryAndCleanEvery10Min: 0 */10 * * * ? + executeEventExpression: 0 */3 * * * ? +server: + port: 8093 + #springsecurity默认过期时间30m + servlet: + session: + timeout: 1440m + target: + host: 10.95.53.49 + port: 9389 + username: hndnzl + password: '@#001njcnPQS' + basePath: /home/hndnzl + privateKeyPath: + +spring: + security: + user: + name: data_njcn + password: dnzl@#002 + #influxDB内容配置 + influx: + url: http://10.95.53.49:8086 + user: pqsdata + password: njcn@#001 + database: pqsbase + mapper-location: com.njcn.influx.imapper + application: + name: oracle-influx + autoconfigure: + exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure + datasource: + dynamic: + druid: + initial-size: 10 + # 初始化大小,最小,最大 + min-idle: 20 + maxActive: 500 + # 配置获取连接等待超时的时间 + maxWait: 60000 + # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 + timeBetweenEvictionRunsMillis: 60000 + # 配置一个连接在池中最小生存的时间,单位是毫秒 + minEvictableIdleTimeMillis: 300000 + testWhileIdle: true + testOnBorrow: true + validation-query: SELECT 1 from dual + testOnReturn: false + # 打开PSCache,并且指定每个连接上PSCache的大小 + poolPreparedStatements: true + maxPoolPreparedStatementPerConnectionSize: 20 + filters: stat,wall + filter: + wall: + config: + multi-statement-allow: true + none-base-statement-allow: true + enabled: true + # 配置DruidStatFilter + web-stat-filter: + enabled: true + url-pattern: "/*" + exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*" + # 配置DruidStatViewServlet + stat-view-servlet: + enabled: true + url-pattern: "/druid/*" + # IP白名单(没有配置或者为空,则允许所有访问) + allow: #127.0.0.1,192.168.163.1 + # IP黑名单 (存在共同时,deny优先于allow) + deny: #192.168.1.73 + # 禁用HTML页面上的“Reset All”功能 + reset-enable: false + # 登录名 + login-username: admin + # 登录密码 + login-password: njcnpqs + query-timeout: 36000 + primary: master + strict: false + datasource: + master: + url: jdbc:oracle:thin:@10.95.53.40:11521:pqsbase + username: pqsadmin + password: "@#001njcnpqs" + driver-class-name: oracle.jdbc.driver.OracleDriver + target: + url: jdbc:mysql://10.95.53.49:13306/pqsinfo_hn?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=CTT + username: root + password: njcnpqs + driver-class-name: com.mysql.cj.jdbc.Driver + redis: + database: 15 + host: 10.95.53.49 + port: 16379 + password: njcnpqs + timeout: 5000 + lettuce: + pool: + max-active: 8 + max-wait: -1 + max-idle: 8 + min-idle: 0 + #不做限制的参数配置 +#mybatis配置信息 +mybatis-plus: + #别名扫描 + type-aliases-package: com.njcn.oracle.bo + mapper-locations: classpath*:com/njcn/**/mapping/*.xml + configuration: + #驼峰命名 + map-underscore-to-camel-case: true + #配置sql日志输出 + # log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + #关闭日志输出 + log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl + global-config: + db-config: + #指定主键生成策略 + id-type: assign_uuid + diff --git a/influx-data/influx-target/src/main/resources/application.yml b/influx-data/influx-target/src/main/resources/application.yml index faed30b..dd97f41 100644 --- a/influx-data/influx-target/src/main/resources/application.yml +++ b/influx-data/influx-target/src/main/resources/application.yml @@ -1,119 +1,3 @@ - -business: - #分片次数,一定为24的约数,1 2 3 4 6 8 12 24 - slice: 4 - # 0.pq 1.pms - type: 0 -server: - port: 8090 - #springsecurity默认过期时间30m - servlet: - session: - timeout: 1440m - spring: - security: - user: - name: data_njcn - password: dnzl@#002 - #influxDB内容配置 - influx: - url: http://192.168.1.102:8086 - user: admin - password: 123456 - database: pqsbase_sjzx - mapper-location: com.njcn.influx.imapper - application: - name: oracle-influx - autoconfigure: - exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure - datasource: - dynamic: - druid: - initial-size: 10 - # 初始化大小,最小,最大 - min-idle: 20 - maxActive: 500 - # 配置获取连接等待超时的时间 - maxWait: 60000 - # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 - timeBetweenEvictionRunsMillis: 60000 - # 配置一个连接在池中最小生存的时间,单位是毫秒 - minEvictableIdleTimeMillis: 300000 - testWhileIdle: true - testOnBorrow: true - validation-query: SELECT 1 from dual - testOnReturn: false - # 打开PSCache,并且指定每个连接上PSCache的大小 - poolPreparedStatements: true - maxPoolPreparedStatementPerConnectionSize: 20 - filters: stat,wall - filter: - wall: - config: - multi-statement-allow: true - none-base-statement-allow: true - enabled: true - # 配置DruidStatFilter - web-stat-filter: - enabled: true - url-pattern: "/*" - exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*" - # 配置DruidStatViewServlet - stat-view-servlet: - enabled: true - url-pattern: "/druid/*" - # IP白名单(没有配置或者为空,则允许所有访问) - allow: #127.0.0.1,192.168.163.1 - # IP黑名单 (存在共同时,deny优先于allow) - deny: #192.168.1.73 - # 禁用HTML页面上的“Reset All”功能 - reset-enable: false - # 登录名 - login-username: admin - # 登录密码 - login-password: njcnpqs - query-timeout: 36000 - primary: master - strict: false - datasource: - master: - url: jdbc:oracle:thin:@192.168.1.101:1521:pqsbase - username: pqsadmin - password: Pqsadmin123 - driver-class-name: oracle.jdbc.driver.OracleDriver - target: - url: jdbc:mysql://192.168.1.102:13306/pqsinfo?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=CTT - username: root - password: njcnpqs - driver-class-name: com.mysql.cj.jdbc.Driver - redis: - database: 15 - host: 192.168.1.22 - port: 16379 - password: njcnpqs - timeout: 5000 - lettuce: - pool: - max-active: 8 - max-wait: -1 - max-idle: 8 - min-idle: 0 - #不做限制的参数配置 -#mybatis配置信息 -mybatis-plus: - #别名扫描 - type-aliases-package: com.njcn.oracle.bo - mapper-locations: classpath*:com/njcn/**/mapping/*.xml - configuration: - #驼峰命名 - map-underscore-to-camel-case: true - #配置sql日志输出 - # log-impl: org.apache.ibatis.logging.stdout.StdOutImpl - #关闭日志输出 - log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl - global-config: - db-config: - #指定主键生成策略 - id-type: assign_uuid - + profiles: + active: bd \ No newline at end of file diff --git a/influx-data/influx-target/src/main/resources/application_hb.yml b/influx-data/influx-target/src/main/resources/application_hb.yml index 057a2ab..c10dbdf 100644 --- a/influx-data/influx-target/src/main/resources/application_hb.yml +++ b/influx-data/influx-target/src/main/resources/application_hb.yml @@ -1,102 +1,102 @@ -#文件位置配置 -business: - #分片次数,一定为24的约数,1 2 3 4 6 8 12 24 - slice: 4 - # 0.pq 1.pms - type: 1 - -server: - port: 8090 -spring: - security: - user: - name: data_njcn - password: dnzl@#002 - #influxDB内容配置 - influx: - url: http://25.36.232.36:8086 - user: admin - password: admin - database: pqsbase_hbcs - mapper-location: com.njcn.influx.imapper - application: - name: oracle-influx - autoconfigure: - exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure - datasource: - dynamic: - druid: - initial-size: 10 - # 初始化大小,最小,最大 - min-idle: 20 - maxActive: 500 - # 配置获取连接等待超时的时间 - maxWait: 60000 - # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 - timeBetweenEvictionRunsMillis: 60000 - # 配置一个连接在池中最小生存的时间,单位是毫秒 - minEvictableIdleTimeMillis: 300000 - testWhileIdle: true - testOnBorrow: true - validation-query: SELECT 1 from dual - testOnReturn: false - # 打开PSCache,并且指定每个连接上PSCache的大小 - poolPreparedStatements: true - maxPoolPreparedStatementPerConnectionSize: 20 - filters: stat,wall - filter: - wall: - config: - multi-statement-allow: true - none-base-statement-allow: true - enabled: true - # 配置DruidStatFilter - web-stat-filter: - enabled: true - url-pattern: "/*" - exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*" - # 配置DruidStatViewServlet - stat-view-servlet: - enabled: true - url-pattern: "/druid/*" - # IP白名单(没有配置或者为空,则允许所有访问) - allow: #127.0.0.1,192.168.163.1 - # IP黑名单 (存在共同时,deny优先于allow) - deny: #192.168.1.73 - # 禁用HTML页面上的“Reset All”功能 - reset-enable: false - # 登录名 - login-username: admin - # 登录密码 - login-password: njcnpqs - query-timeout: 36000 - primary: master - strict: false - datasource: - master: - url: jdbc:oracle:thin:@10.122.32.73:11521/dwxb - username: pqsadmin - password: pqsadmin_123 - driver-class-name: oracle.jdbc.driver.OracleDriver - target: - url: jdbc:mysql://25.36.232.37:13306/pmsinfo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT - username: root - password: Huawei12# - driver-class-name: com.mysql.cj.jdbc.Driver -#mybatis配置信息 -mybatis-plus: - #别名扫描 - type-aliases-package: com.njcn.oracle.bo - mapper-locations: classpath*:com/njcn/**/mapping/*.xml - configuration: - #驼峰命名 - map-underscore-to-camel-case: true - #配置sql日志输出 - # log-impl: org.apache.ibatis.logging.stdout.StdOutImpl - #关闭日志输出 - log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl - global-config: - db-config: - #指定主键生成策略 - id-type: assign_uuid - +##文件位置配置 +#business: +# #分片次数,一定为24的约数,1 2 3 4 6 8 12 24 +# slice: 4 +# # 0.pq 1.pms +# type: 1 +# +#server: +# port: 8090 +#spring: +# security: +# user: +# name: data_njcn +# password: dnzl@#002 +# #influxDB内容配置 +# influx: +# url: http://25.36.232.36:8086 +# user: admin +# password: admin +# database: pqsbase_hbcs +# mapper-location: com.njcn.influx.imapper +# application: +# name: oracle-influx +# autoconfigure: +# exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure +# datasource: +# dynamic: +# druid: +# initial-size: 10 +# # 初始化大小,最小,最大 +# min-idle: 20 +# maxActive: 500 +# # 配置获取连接等待超时的时间 +# maxWait: 60000 +# # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 +# timeBetweenEvictionRunsMillis: 60000 +# # 配置一个连接在池中最小生存的时间,单位是毫秒 +# minEvictableIdleTimeMillis: 300000 +# testWhileIdle: true +# testOnBorrow: true +# validation-query: SELECT 1 from dual +# testOnReturn: false +# # 打开PSCache,并且指定每个连接上PSCache的大小 +# poolPreparedStatements: true +# maxPoolPreparedStatementPerConnectionSize: 20 +# filters: stat,wall +# filter: +# wall: +# config: +# multi-statement-allow: true +# none-base-statement-allow: true +# enabled: true +# # 配置DruidStatFilter +# web-stat-filter: +# enabled: true +# url-pattern: "/*" +# exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*" +# # 配置DruidStatViewServlet +# stat-view-servlet: +# enabled: true +# url-pattern: "/druid/*" +# # IP白名单(没有配置或者为空,则允许所有访问) +# allow: #127.0.0.1,192.168.163.1 +# # IP黑名单 (存在共同时,deny优先于allow) +# deny: #192.168.1.73 +# # 禁用HTML页面上的“Reset All”功能 +# reset-enable: false +# # 登录名 +# login-username: admin +# # 登录密码 +# login-password: njcnpqs +# query-timeout: 36000 +# primary: master +# strict: false +# datasource: +# master: +# url: jdbc:oracle:thin:@10.122.32.73:11521/dwxb +# username: pqsadmin +# password: pqsadmin_123 +# driver-class-name: oracle.jdbc.driver.OracleDriver +# target: +# url: jdbc:mysql://25.36.232.37:13306/pmsinfo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT +# username: root +# password: Huawei12# +# driver-class-name: com.mysql.cj.jdbc.Driver +##mybatis配置信息 +#mybatis-plus: +# #别名扫描 +# type-aliases-package: com.njcn.oracle.bo +# mapper-locations: classpath*:com/njcn/**/mapping/*.xml +# configuration: +# #驼峰命名 +# map-underscore-to-camel-case: true +# #配置sql日志输出 +# # log-impl: org.apache.ibatis.logging.stdout.StdOutImpl +# #关闭日志输出 +# log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl +# global-config: +# db-config: +# #指定主键生成策略 +# id-type: assign_uuid +# diff --git a/influx-data/influx-target/src/main/resources/application_sjzx.yml b/influx-data/influx-target/src/main/resources/application_sjzx.yml index e04c7dc..ca9a589 100644 --- a/influx-data/influx-target/src/main/resources/application_sjzx.yml +++ b/influx-data/influx-target/src/main/resources/application_sjzx.yml @@ -1,101 +1,101 @@ -#文件位置配置 -business: -#分片次数,一定为24的约数,1 2 3 4 6 8 12 24 - slice: 4 - # 0.pq 1.pms - type: 0 -server: - port: 8090 -spring: - security: - user: - name: data_njcn - password: dnzl@#002 - #influxDB内容配置 - influx: - url: http://192.168.1.102:8086 - user: admin - password: 123456 - database: pqsbase_sjzx - mapper-location: com.njcn.influx.imapper - application: - name: oracle-influx - autoconfigure: - exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure - datasource: - dynamic: - druid: - initial-size: 10 - # 初始化大小,最小,最大 - min-idle: 20 - maxActive: 500 - # 配置获取连接等待超时的时间 - maxWait: 60000 - # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 - timeBetweenEvictionRunsMillis: 60000 - # 配置一个连接在池中最小生存的时间,单位是毫秒 - minEvictableIdleTimeMillis: 300000 - testWhileIdle: true - testOnBorrow: true - validation-query: SELECT 1 from dual - testOnReturn: false - # 打开PSCache,并且指定每个连接上PSCache的大小 - poolPreparedStatements: true - maxPoolPreparedStatementPerConnectionSize: 20 - filters: stat,wall - filter: - wall: - config: - multi-statement-allow: true - none-base-statement-allow: true - enabled: true - # 配置DruidStatFilter - web-stat-filter: - enabled: true - url-pattern: "/*" - exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*" - # 配置DruidStatViewServlet - stat-view-servlet: - enabled: true - url-pattern: "/druid/*" - # IP白名单(没有配置或者为空,则允许所有访问) - allow: #127.0.0.1,192.168.163.1 - # IP黑名单 (存在共同时,deny优先于allow) - deny: #192.168.1.73 - # 禁用HTML页面上的“Reset All”功能 - reset-enable: false - # 登录名 - login-username: admin - # 登录密码 - login-password: njcnpqs - query-timeout: 36000 - primary: master - strict: false - datasource: - master: - url: jdbc:oracle:thin:@192.168.1.101:1521:pqsbase - username: pqsadmin - password: Pqsadmin123 - driver-class-name: oracle.jdbc.driver.OracleDriver - target: - url: jdbc:mysql://192.168.1.102:13306/pqsinfo?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=CTT - username: root - password: njcnpqs - driver-class-name: com.mysql.cj.jdbc.Driver -#mybatis配置信息 -mybatis-plus: - #别名扫描 - type-aliases-package: com.njcn.oracle.bo - mapper-locations: classpath*:com/njcn/**/mapping/*.xml - configuration: - #驼峰命名 - map-underscore-to-camel-case: true - #配置sql日志输出 -# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl - #关闭日志输出 - log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl - global-config: - db-config: - #指定主键生成策略 - id-type: assign_uuid - +##文件位置配置 +#business: +##分片次数,一定为24的约数,1 2 3 4 6 8 12 24 +# slice: 4 +# # 0.pq 1.pms +# type: 0 +#server: +# port: 8090 +#spring: +# security: +# user: +# name: data_njcn +# password: dnzl@#002 +# #influxDB内容配置 +# influx: +# url: http://192.168.1.102:8086 +# user: admin +# password: 123456 +# database: pqsbase_sjzx +# mapper-location: com.njcn.influx.imapper +# application: +# name: oracle-influx +# autoconfigure: +# exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure +# datasource: +# dynamic: +# druid: +# initial-size: 10 +# # 初始化大小,最小,最大 +# min-idle: 20 +# maxActive: 500 +# # 配置获取连接等待超时的时间 +# maxWait: 60000 +# # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 +# timeBetweenEvictionRunsMillis: 60000 +# # 配置一个连接在池中最小生存的时间,单位是毫秒 +# minEvictableIdleTimeMillis: 300000 +# testWhileIdle: true +# testOnBorrow: true +# validation-query: SELECT 1 from dual +# testOnReturn: false +# # 打开PSCache,并且指定每个连接上PSCache的大小 +# poolPreparedStatements: true +# maxPoolPreparedStatementPerConnectionSize: 20 +# filters: stat,wall +# filter: +# wall: +# config: +# multi-statement-allow: true +# none-base-statement-allow: true +# enabled: true +# # 配置DruidStatFilter +# web-stat-filter: +# enabled: true +# url-pattern: "/*" +# exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*" +# # 配置DruidStatViewServlet +# stat-view-servlet: +# enabled: true +# url-pattern: "/druid/*" +# # IP白名单(没有配置或者为空,则允许所有访问) +# allow: #127.0.0.1,192.168.163.1 +# # IP黑名单 (存在共同时,deny优先于allow) +# deny: #192.168.1.73 +# # 禁用HTML页面上的“Reset All”功能 +# reset-enable: false +# # 登录名 +# login-username: admin +# # 登录密码 +# login-password: njcnpqs +# query-timeout: 36000 +# primary: master +# strict: false +# datasource: +# master: +# url: jdbc:oracle:thin:@192.168.1.101:1521:pqsbase +# username: pqsadmin +# password: Pqsadmin123 +# driver-class-name: oracle.jdbc.driver.OracleDriver +# target: +# url: jdbc:mysql://192.168.1.102:13306/pqsinfo?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=CTT +# username: root +# password: njcnpqs +# driver-class-name: com.mysql.cj.jdbc.Driver +##mybatis配置信息 +#mybatis-plus: +# #别名扫描 +# type-aliases-package: com.njcn.oracle.bo +# mapper-locations: classpath*:com/njcn/**/mapping/*.xml +# configuration: +# #驼峰命名 +# map-underscore-to-camel-case: true +# #配置sql日志输出 +## log-impl: org.apache.ibatis.logging.stdout.StdOutImpl +# #关闭日志输出 +# log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl +# global-config: +# db-config: +# #指定主键生成策略 +# id-type: assign_uuid +# diff --git a/influx-data/influx-target/src/main/resources/libqvvr_balance_dll.so b/influx-data/influx-target/src/main/resources/libqvvr_balance_dll.so new file mode 100644 index 0000000000000000000000000000000000000000..b3058734d53dfb944691677be16c63d14e9914e4 GIT binary patch literal 114976 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

<*jeAfOMwR?nz}sXxIKrXcH;r%V^&Oc8A9&!k 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 T4?6T%{h$5BOP*B;{M-1Ly(< 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

2-1+=Wo_*MX`YOV6Qn*Cvnup=a9Fk@Tm& z4sMu-c}5C5B{o8Fg3|T&!q2P27XRkVqnj+1{ozE`+i-lw(zdl7hYYmU$ca}IFtm}c zMl)^G){|Ib&~GM_(StlME{FINb`57GOk_4eBWe(y4(r{yo&y+e$Nj_MuiSwXbSoc5 zMGZIgo~PF_hrr7kVt)@ua%6{tPmJ%ew8y^3(xNWovLYkMOcFn-&g|yq86H=|-O=}6 z)MZxmMiUn`N|NTF3%oZ$lTy7HdyUl_hKutv2QdSMm59DU(=vZlXM7%P47vsuKk#wk zv9AL+tj0qA&D0;Phn=|hb7emrMJt@k=p=PcU86_WK2U113c9xrpABw~%63h0R$O5vQ zI7C@zStydFkrNEQ>Z<2i+Er}V*z=uB_G?&Q1^&d7j)4bwzR?)X!G=jN^~yxlessBAjeKeXl#Pl5BmhVpdQ2V2*sYUIV%G_)OP7TNK~EwY`wzVM^gtsT&GmMhEKH^ zw^+<9Vw;A2)a}}$uH^Dx-=sIyZuX0_0yTAt?QsQWO&y$Y9ce8M(s!y3e!R|#1hwvY zM7>2@-PH~76Wp8G9f{T7-+i~=Bo0Kgz=~CD1(O;`9l@)G>e2;JR-S#Rd6_g}3$t7w zsH<3jr0CHf?j(6h2g}%Vmi(^D0SOd{^EYl7L#z@!;J_1j)v@zqTDWf;>-Xr!i>L4fkQ`*lYrJ2tW$} zK>|FMT>z9~N5hN}AF+R$F(M;|BVZ5k5RcVk`P}Df@h{DC9amTUsV7YJh(9!CrNWvj z*oypEUFBmPQSYX#z68P=A85*Q;7ReMg`huh@k1<$dX}A2rSV2m9W6ahAR*ajfw>=A zOJuBWu5Rrq>p2m9K`7!qtgui{v$jiFTg02y!EevQd@v>3!4qsa$Y<+mg=DpLilfrY zAI|0u6embivWKe9FI49aoc(LQg1?DQ)OItR)2H;$CDe1(i48t_ap}9A z(uN`KJ-)fn0szL8DL6cd{cdB0qXp8zSScK+&6;te69~INT5N1i!#gi2*~2L}xza_O zk&{Dw`62Pu1Z3vBC-9G2YguZx;eg-D<8XTPlRo|H(4a;!3P z#DNLgfKswXfFrO9j5fiN3C#@sVLdm~CTf!6elzNm(E}*Ju>M?Y%9?>(@almXkE

    MHdDC|P`&W4O^v7$RfD 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 literal 0 HcmV?d00001 diff --git a/influx-data/influx-target/src/main/resources/libqvvr_dll.so b/influx-data/influx-target/src/main/resources/libqvvr_dll.so new file mode 100644 index 0000000000000000000000000000000000000000..2d7dc0365d1a0b92cb3766d8d274ddeb86b889e5 GIT binary patch literal 207680 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

    MA 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 + + + + + + + + + + + + + + + + + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %logger{36} - %msg%n + UTF-8 + + + + + + + + ${logHomeDir}/${log.projectName}/debug/debug.log + + + + + DEBUG + + ACCEPT + + DENY + + + + + + ${logHomeDir}/${log.projectName}/debug/debug.log.%d{yyyy-MM-dd}.%i.log + + 10MB + + ${log.maxHistory:-30} + + + + + + + + + + ${log.pattern} + + UTF-8 + + + + + + + INFO + ACCEPT + DENY + + + ${logHomeDir}/${log.projectName}/info/info.log + + + + ${logHomeDir}/${log.projectName}/info/info.log.%d{yyyy-MM-dd}.%i.log + + 10MB + ${log.maxHistory:-30} + + + + ${log.pattern} + + UTF-8 + + + + + + + + ${logHomeDir}/${log.projectName}/error/error.log + + + ERROR + ACCEPT + DENY + + + + ${logHomeDir}/${log.projectName}/error/error.log.%d{yyyy-MM-dd}.%i.log + + 10MB + ${log.maxHistory:-30} + + + + ${log.pattern} + + UTF-8 + + + + + + + + + + + + + + + + + + + + + + + diff --git a/influx-data/influx-target/src/main/resources/qvvr_balance.dll b/influx-data/influx-target/src/main/resources/qvvr_balance.dll new file mode 100644 index 0000000000000000000000000000000000000000..97efdf1606263fe93985904ced11e0306de38a8a GIT binary patch literal 220672 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 PCV&ZG0+_)6ioo9hNKhsO literal 0 HcmV?d00001 diff --git a/influx-data/influx-target/src/main/resources/qvvr_cause_dll.dll b/influx-data/influx-target/src/main/resources/qvvr_cause_dll.dll new file mode 100644 index 0000000000000000000000000000000000000000..95328f1aaad28f40e168cab87e1bca74a2e4f02f GIT binary patch literal 47104 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 V*yPyp@w4MUjnCh8!F%sz;BWbV9CQEx literal 0 HcmV?d00001 diff --git a/influx-data/influx-target/src/main/resources/qvvr_dll.dll b/influx-data/influx-target/src/main/resources/qvvr_dll.dll new file mode 100644 index 0000000000000000000000000000000000000000..60d74a998a94f8e620aa44edecaaced69145fa1e GIT binary patch literal 50176 zcmeFa34B!Lx%fXxW+Xzwnb<_B#WvQVH#i8`sKq;S&A?Hu|6FyaQk{e|U!9XSSh=^R4N&fFX;%E)G>!0-);Y?}SU)HABElPA zot>7d+&j`TmHVSqaWmGRRPM%C?^N;Mxvlh8Y3qwdHmT6zn6>;Y$CiTgXC(7~QFm$@`1LQ6m*P&Q6QVB6X&xZBac?kz_tQZ3y1nKRF!p?5Hz2Ye-L59ko-RW{vxX zPb)OCZ1&w{#QpKd{79E&?9zUpf4L6F%#rhF-CTCF!!bIW1nP90%irVt_4!voQzNZx zjwipw{I!xOEAZz&neY}k9Cah-SsB$B8LMhD36yqr@)eAnzhHhTVKpbrjhgTm?F{|$ z&7N~78D)-Su2j4ApUXF{f6V`PLVC2sldeb0JZ?Q&;TaMzCVM6YjrOCOJLJ&|^Xo#! z>we>;-#FqoTD7U0w7l36tvGYn&m0b1*GAl1w5hxKYb~taQFeuH#I#ZF1(}I@JyPfN z`*zIl?6{DG3$(9QsYx~JsoGhojcQmhAX1+w|EMEXs&AIk{~9zJtkN;7bPJ_D)tkz4 zZ@HzXeC(*73L;hou|)ZYRB%{I`*fq>mNim-us=~J6%_jF=YQ03QDJpm*;kY0kB&>0 zPWMOZr2Vu)qm@3ne!y6Kr|{*>!KWJm&lqj|DV+%^@cT~chRl<}JO#7~ujvMJB~^LW z9My`4jkgQrX?a_;yf;WF8oK7_c&#YoUa4pFQLU(5A|-cGGk<%T$D`VG=3+$MZOylW zhqq{RW7Ew8~!%UU&*6v?CIHCovufvlUfn>I;2*>@)svVNRv)ng@=>^rJu z{nSHL!lCu{ZsVHLqY@m+VBPI`T4ge3$@|n*XoAr!R^ssSK zj|Mz51N@B8qmwsB(KoABIsH+ADae5>XDtjKbIty}I3 zdALVuIxKNu)XNoT$BaH^M;<4A@(egINk3A^hofYsD1hl-mBLGJxDe(hD zYk6Jdpo_()$Wh@L6W>Z~$e809t((s}T2oSF9GQadUiRm(@t&$k4|)Hp<+ba> zD`Xy~d>{ant9`A&akNl#KXRF4^r=%pW20Z2x>@%&2!sc!8C>4ZfHo!PHr1;(X|q-O zU-d1?u1&3zm~BV2l2!&nFN> zg}(GwJSYAXIsDp`Iufk}tHQGQeRhIwY#>1@40tL)z<~2senZYVL_%|9m@)a;1euXs zRnDajMR&j<0zz0o_jEndHKd}B%ANx<9NO0;6AkCdY=CLS_d6wqz!m~k&Xol4)Hv6O z2bg;mK!Oq!wNdM2XRc5XJ#rwW{6*=KCpVa&-%v#l@W8sum;n$1B_5p;%N=Xt3EaVY zWTP|eJE7HFcq)+qKkBC)PAxQE3mL$;z)4ZS2zf>TSim7I<9W(cXL+9R2xlbb5zk)B zbHAt4^3-@7DJtn1&(p+&j13{<8P8JU^vI`9t!5RGx_Lvl9y^$-o2vy7^+bKhbTY@x zRWJRlddxBNpd(r--PO&Y+aQ9>QGciSRMN54@kCGbv7YFzzR_Jh(cOKcyY=pxx-OtH0j1Jd!Q;YpTux=LaS|-nSff)40%6dbuJ(H zC}Hp0c*jn`t6=pOJWNSIAizDCKYR6x0k2{xYf%hHi+}PX!I5HU5nwkCP#fuRU&0!@ zYpu0*pJf4P{AHDKdXoUD0KWp#{Jxn5j6qfaSol|#^ANS1E0Cg1-9f@G66z%(aLB1A zHUxbiX*J)2TlKBPTfdPJoNSJ@0I_B+Ie|u#Lk^r5?R;X<_~c((f_(JN)ZK zfD6DhCh4ZR*Ci}q$_{Oc&~aBMvMLkV8BYVH^LLP85}BxGuMUp?PBk2iB*4gLs3K@y14hPEbp#SKyIN{x;a6DTGi?C=)sA`R zIkZvDccm$jz`fe3$jG$oozRjMk7T`nSPD2*rkG@EmT6&yht$y6fv^xE?nlcDW zB~RFuWY~o=dYj8y@g#|Qq{*#E;wf774AwemB!a%z7G15I%VpR>8MAYZ?rovrrFPF{ z6f67pJZq_Rwufl$@EhCxM&mjVIjug{mFjH{mDYtyKMDJqG*e^>5)1Q>uk+Tob%niM z=DZXoap~rInci#7t5#U}shcZhb%LdD3A$&ji~rkA0vP}U;mVlwP{wEx6_QK(C$lId z4^SojDhaX9FO-}z%#Us^aRwtFrIbG;9JxR@I&Ue|<~G7I->-vG6uX|GuOM1o{7|hB zgCf@-CE`Uv5z3nI{TZabg z=2fGErF(Q^n|@-qfb>k=+bjbw2zr|&e7DF<^Fl_axJBC6=%913h~ef#0P*D^#s-Sa^u|JFxI`5|)bh53%xQCi-W@@6Tz1&o6863>VoDGH(A))wf{{A6 z=GHqk_awK-tL}nsM2M6_nmgSJW+0OgJCxW|V)a}oTXqU*xEX1{NI}TAvErEkRC=@m zh!~>?8cjiO9ZcL=aZk`JNCohMOb&yB3p?rKWIc8uHE24Q(K~vkCt_jKxe`d6)XmQj z#pFv05YILv77Mga5*!M+iGlr>GzbX~rFW5_gEx{R%b6-fHzS2EfdTOP-_xB%S0K8( zvzO82B-**o%vcsQUJH7W4ctMeLer9ZEw4=x^0W0w3^4(ww=e&AVf7xZb~j@Q08FDp z<^xYSAyE0pL#79YBjkJ9WFe(+?21sx9N!%@HU}XOL1PE3aiW=_D1_nf7RDSM*RGpC zdYod0zcadQCa7unk449=H2huBaZd+9*z#9GzReW_I>zeNdlrvj?Ex^R%gkPeKMK%K z2$|It^g$*{r!DU$1CII~r$0(mL7p1&2cfj1;j}mO#KvHxULk{4J%z?XY<7w)NDncb zTh(e68jV4NR^M5YXW?hCv`%(gX2w$8te!+u0BkeB`>F%+L-*}m{8n#~VZd|0{CfxV z=6^bwUpEV%E;JgL{gr|QxqcXq8Fs{vT&{>`VNJfU*8yr0Z`94}K4V!z)in^c`4H4B z&7z~BYPN!>#oYh7n6-Ul6z%fGDt@OUy`2B~T7`%ssk|@L=Wb}GQ?`R+f{_nX)YODv zkVRVcb=|_Y!EA-|6P=pO<2*rpP+jFwcpfs|SMmq&oMGcPbT5hD^{l#u-|NNqzryeP zB$M&K8Nbudh~MtNf!_+XH_*2}sJ-|fKy9@@`d^`UY7csY$)S|f(Hor4U}x~3L2rsW z`=Ga|Mn(&c@6c-ZF{r--$8Y>X9Pgp0{{>{f^uGz&Cnk|yp}Fi+#;CErEKDw7Y=qJJ zj{g1lP6-jsDe{ltJ6n|=d`EHv-&4Q&KMmhQ-s3isPw0o_FMmY?w~<+L6-)2OF9pBz zcZAFpN>WU#Q|!A@@Kv$z=f!8Cx3C+?_WH1y0qM5cci7jgMPv(iM)anLV&6CRvhQYL z-(hbvXa@Uk4SU;FcY5GW__rRZKLh_h1AZ%psSq4rw(xpEry;_?b>FUvKO!e;=0%kx;ajGHv*%K$l~2MCVBT#x<4UUsG=;pPdhEx*r2>WFika@~i{Y;`s=ounZ}>tC zxAhPI1Mqv2!f%mDzW}wr-j6Atk%{*rb^pwNgM)t_qeqYYAB52}6$c*z7SbF1^{hdb4%)%O)zA-fZ2y*}BOl!l_pMU4S4AYFraE zSFQU}EbTfo`{nCRCx00)hrK63m0Dw2zhOB2#!?w-)ZgtlDrc!dNPTL%v@>XIi`UIl z>*>nnfC@cB@P+g=gj+Lb2%a8&yH+$t8`Z^$06P7+Q}@*`In%C|x8pEU7)Qy75t3@4PsZcTpk$ekc+d?N>{ln-Kbu;q> zx;*l3yG7R)x5U5v5qe%q{X~YtBI2L%6B&s_{z3+VF6fe-Xw0BL$X?p0Hx|0sHFU7M z-jcs3zbI$TASc{*_qdK&`^GrHfrPi zbZyk(g=zl82B>`*o!vP9W&%+B^opCJ_g9NnBGG_2iCzQgSRcET*;sT_$JN@X&V`iS zHa}VRVu=}+Ec>@X_EJtU@;^w_2W6IH>`|ISzU^Ag^(?xaew?H8li5^N9inCV zm)IQnGlhzp4^l+Y&o@k0@sohngF6gVPcuy}qVZ2?PSbSax34?u3Ft(S? zjA|!-#S-d9>r(rUtl2dvtoBsbX|?y$q^$a5a#YPmB2?NMDy?}y7C@BiM%4q-*+O6Q zqCn8BTs!Kvv_fwTTv+Zm>P}zpX|mqY{z{K&@I0CBR#Bgn@6<-_yeG4KP$>F{Y9jJc zsy6ENyUw9wi!))mjChAu^KUGQ-`Jy9A7A`+4!mU4eFxppGiaSXGK2n<*AO16i_o-SohS$_n>-vo*D%A+5n%NJ68x!p)KguH`9um3!Q0~ zx&FIauuwk+=Cm#p@KH6;4zx@rv9;otNwDz>*eE?q0&bs9Ws$qwOjxzRjU<~f&98cb6iR=x!`{8n*S_eVWkjn5zJlg` ziL~K3*$--?u652o8+ZW#Vs|OpSI=o^bH)1|15JOzZ`B~D0R@0*wb&8_jh29KvM02t zuup}{tO}jWb)(IKM{SgD)r`_Gc2_a@ZXLA-eXmx$<2P1I&#E_-bB4RqANe$O@il#F zi}cpk(!ZYb6R1h^73vb$pd9SG5Gp|L_aGEE;bO=^nDdYaTvYZ7r=nxuDqS{0B?(kIrWxA{y$J*~T$ zNFkqf&Y*8=#cLe{8M!naFce`g_cJq#@9b$AdeLvNcFRHIwDEpnd*}F>@jjFOYR5T# z3pS+H4wr%s0ln(!%%uW63*x?|`tbKdoJ^%Gq2Ev|$^Nw(HMIj})#ARe)&m^?c7N!| z@+USYds@8-=onZSeaxzHXZ4Qq2?3)z4oCpOg}&BBeY^LgzXKtX-Ls&7Zl4KWmeLoR zdM3E<(sH2wMeBJktgX+2?s_?mL3dmjh(1sRDi>OdYei;661j^9{3VwR#tDD)uJll8 zlQ5c~xms**EIOe`Mttktf&&{N-q}I(`V2cs7)tyPBq2@|TFC7;9+b0&$jOw2m-SgN zMO^z&FXjr30(Jr4{`v293@D8Lhc&mgQa-VX`UD`VH!U99Q;%NS2IMEvS?0hA0wKkW zN?+g>uxe4bT)kt-J3W}>Hx$`I640O%R+VK=Sl@uK)nnZ-<@iPCtm)hz2sS_BkrSJs zanmH&M&I)$4xMhOvksl6+s97H117O2>38~5d1wvb%OTH?QGwbv1#u=dVEntBzJ$z5 zQEcm_>(t4NaYT>aZ=Y};=7>O#)_6n(wk}|x)pai)LS5=eK{xN6`IDWQoGgf<+`KzQ zr=kzPJeV^9rPn8Rj2v@~4jQ}Uq$>|WOSHkB-1sMNAs^ax1z=$3xC3~(H)F1WcpDJzot~fy?SA#FZ3H#wK8GRW!90$ zcibw5zDCD&Dlh$rE|cAc3Nc57-X3X%7#^YPCs-l+M(8iotdOcy_9eX)9_y`8_9eX) z9_v@(v3?aE>sO)dV0tU;>a9?AFufIa^{cR}Uxi)$DwMrWZ-s14m=85%*_-rM*xj$f z?tT?^Q=#nmwd&s@;f8#h7R?D-$9f?nb}f2|u$RM;)8?7&5HV_=|4WUQ{~X=6@u{~d z!HF1R`ew~+RS41$^um3*0D;MbgGL*I3LVkCZS>WtSJsPoYJ-Hx80_3CZ&_m~IEYrM zV|61n>Rd$(2U`+@Ljcf~01g2_Py#pv>ZYjxjJf*4RgX9X zta`*DVAUgzu}n@TsYe`RTsrln6KB;U4gsqkaR^xTh(o}tM;v3B99B|~IL5dP>d7F^ zsz)3GRz2bnu<8+qfK`t;oOQUZm41bl4*Rw*`aTnjGKg8VXOt32~@OWh=d5ubdjVYJG=O^HD`ia0ZNt z=>cQST9Mq1wU6KwdRq&pkJ=+WQ0Gh zAv$45(}Z-XuFyC@pVG7%4XEwc0lRgr_G7Xc6EghXdcTiN+4}_T4kc^s+mSxKh z?hHhyXUl=vH|)w!FLPSA0!D|mOQjXPX~Iw(hyNw%DIt%9a7WngWwv{j?FMW&WV@4X zx5Rd5+3p)DslN|&rPuOO*Z{!Ek2*+LKU$19JTkDsHBGc9r2PoDP(2_ zksIQ(U<0Aj3F&^b;8djRtJ;d(FNug&xAG;KJ|M_46R?Wt$EuUZ{fF;jBV^!#6A`xA+lo1Q$iyhBi;jFS5 z2%ELSpyA;*b6f}b3+M9I+r+l5i|x4IST2ko{;Lc3ge55^TOdcU&paqKi0{P*g)<+$ z2IDuIrJ|n`UHoWaw0Xj^bK{r3DpU9q=_FMNbu(TLNROvG{oYRlMuYL%wPwcJ_$F3W zP;qoQ8`rGmqY+(+N5UXO{3$yToR!4O`X#O=u`vH#Nf<+dm>aFUp0WCkEochCfy2xM z6HqNg1ltcenhXc2N~jR3)lR&;Y_@V3S@)3}zN$LRPX(d-qV_84`Q`urMe3( zRHR2XxG^u#YBiJ@LErWzAz3^To~#pjWhVmg(G%&28a_4K<|FQR%IOLn-pW zvOf9@+E$!GR1+FK_b)}25{OnVwfe<=zkQ*Aa0=F*M2oc&MHDaAM(tb3v2s>)DYa{P z`=nH#4jm?wB23w8!ozZ(G2d$-Bt)W})+ge$&HIk*Z(~^&!)|wi}T?X={s(^`|{s2?=#Y3=U5tz|^-l^j5VJM3-H zs;^c;(N@ir5!PJmMJ*yy1DmlWTdN@(2VH^Ng~Xg*{9P`*v!zvgr>S@95@lg;<2lm*0TF ziUPa|iXjE^I`z^;-M&Q*&2*7BX#QjtdpX@4`e{G?5xw|z_t)B#C3$JL*keEJ$R((` zU+BL2r{ez6QSeg?(WidE-@9y;U!~{8hwwCteRiAt#H5@kV|Pf}yLg((yoWzA&~8AN z+Nf;POIiuajSE-ze0n?eIHucTeBB_HrdWCxy~bY~5oqpJg38-WUdp^mrV^&HNX$-O z7xf#*EPF`UN*K~C#;!#T=*i;lTdir{jzCIfo1{~jEd(&G#In*oY!`kar*^5fwc;&k zlgHjHk#y~5X$~9nedKUwUMHb|RuYqO?#5U2z64vv*Cg5ALjc!T`BhpGS6 zX8CDc_#LZfy=J)czc1~$hkcv&lnuH2l5eP{r#8bwro-imGk;G+$5#-hMj%ri=nz54 z%p4>BxA7~p^ikVb?S*GkBuitp57VxD?0XzxC7Sd|L%J+{%~wGPtnoMpw0I7}7Ir?t zNTX;OILqFU9`^0mYMMVI8>|UgpwKMwq(qmuyG0ofIgSBK<_)K4vF#ujRdNpX*Z1Kc zLMdqkhwFAYH!lUvZ1O3Q!0xrBRlg0;YkKOgS}r0Gx}Et0g$+p24v`2_BvWH=CRlGz zCaJhX$iCupsy5U(c5Mh)l2I(B{7bD|N#y%e1a^ax{a{_sGUM_-ydJgQ*4y{N-EL{Yi<@G;SsZq{>rg zd1{o=zu$MYwtBNuS{U(}5T0P#hr0RLc`j=89)}A3#6FJ#YJZ~$4W2(G3DHZ61Q9b$ zQKZ?zLjELV2#h+!-KKIUy~a8$od}?zCq9`%*?L+L@eqa-rrg&RIbfGWj&BCa{P(FFIk@;rgL8K*TXA zX4jNs)zm_pB`ijfoJM9ASk*wPScFM-&g+OI@e;3cOZFyf-6LW8pV?x0N`MV0j8+28 znkqyFn#0ATfGSq>SGw0qHN)PRLouilN@W(ic!$s>MmpW~6}vvy^W-46oQq;-$|V%$ zLntRDV)0$y6Bymzlm>=DX5=7yI~M@NHouNBDiYf)8Gj=gtqU-$jUd6On6~^vkV}wE zSQaeLuZ^nts`H=COzojM%m1qEuDntVK2~dPfq!lw2|QEJsIT#*URi5$Rn?o_qxhBlU)b)x+S|=2w-eK z{I-~b?&8hra$PYO?27lZhI`fZr{Yfu%JqvPjEiJnHJyc?zC}@|?eTpxdsa>m88y2` z3c%$Wa=Qf?(3lI#en6M$08AR)AzXL5D@K$64jodGCM#EEt?tw|?HX!uXWl{<*49d4 zt+feocge;2n%_>rrhs;0+JrWCm~ta7(shs<<6Wz_Y;UA?wmi}2IYc1!bv&jyjrWB{HdIB zztR-&+&Yl#A+yHQhzlp-wqM9IFCbU`#Qws#Ila(0RA~G#qtH0zH~!Uad{k%@XLCaC zH-g>1mO{fngd3XL#1e42*1)@)QM1Cf#)7QdAu}a0a_>FH54fysI z8o^vKdYWg@-H8V%C*m*0xswWgAB$SPs8E~uncoMQocK||_og=S&490gtUI~6DmOpp zk#NL+Wx&%N;KJilRXKO%L_|o`1+M(M#9B?pq*ja?0#|+y-JR7dsi8=l*euy2b!h?L z6RQ1y+yv7m#^{6J40)X7kS>@3kBeBkA+cu>OJ5{*0I~E(V$)UZHiNhYX8haZ<)@vZskf z-bt66Wpe0JXwLDR6-^Q8TyB7_C5m&ZRFMYcTt=!A&L{Cn&ZqmT)Mj0)NkdD7m}RSy zv^+~3CnhPN=OsmUZo64Rd|pzl&r52e@+{qyR5MRux23#_KDZYq+>wEd=b4T2?4LGU zgNsX#IKG;4J+8qeI?CvkjcahYA9easmAVyc-+!JX_n*r=L*x>4E>~ma-V#@$LdGR& z-#DD=Hx7hLJ443F0HB+zqir>|h0SV5!Ix9wvS%hJ8YrSNem|OvESuxy(8=D|Az#;1 zf~KkR-_$R~bKeX}kz(;5_N!^M^Daq|qVa#C43%G1UYjEAP%$ZzAwKp@Wu(&hMWh7H zNA>rAuF9Z!w98OBz6+KB3CQ^|v&WGo8t7o;6ubV_OrRKRo8RpYdN-)MguRytl{`bK z$gx^cQx##YB{VgwYRLL8PnC<)*CCk}8C@#1Sgu#p40+K?8IL$x6zR57tTJ_W88)j$ zhJ!;LYO~5Tk^&vUrjuJ0t3#L&T^=;6WgubiXIRxQEw#JBKos%Lsv02ukdst( zui*{31UN~@#-d0J^=FD=@*Z$ZrKuP3NN_%3;kE^45h+Qz{90H(>v}F4)w7Nn#@8eJgCdB1=q%9poN~n#T69Z`Y!)28~mwvmOk3Pa3Ig^3NX^ z#rze;tu8m94h1XY>C(~4m^gZ*Bc;4D#2gmLJj!szqG~@q4;zgEgPS?#NueYR+fep}Ocj8yCe38vM_RhXc$LHCL-b70^4>{U^A zTkoLRvb19dI1}_T@oEIj`dsYX)`h_al-69V<*J%FK0TPIXZRCLj~WnW-^#V^kAkIb z+^li?p_v92PfUd-jD^lKqLwHLpFBfhfm}z;BiBhh-A?Q1`=pt!SZpHc28oAV! zs59#|WVJogLR@Z3Mng6H12e;l6sl(neL8Q}Ti|7XLq(HM&A zxq)cGkmw|Mw4UDce1#C`%0ub!IW84HDYu1(-z`^)3s&;8@@|HWyGCAvz+GEpxsS_h z5QLu`gUcaWid>wG?Mo#JQ}9sf{zOicd!nJzN7Sjr2%9L+C?E6p9;EZCwSHf>wt5}>Uasp=cD0FLU9S*>VaqBhKDwk>RKMCIqsSW85gQZr6wN1?2JlkurUvn%#%Duq`NtlY@-^|>Um zm8q9BZE8COcdKM88m)pvv!55URN#WLc?{#DS9{6zI7m!v9@pXC>1x!q0eiD z+Q_ZN!Nz1rN!xVGHWO!_Oq`m-a~Y@ie_jDTgHs6P6_*wY%?B{AXpMuW?B}J!JZ~`Mq^46@q~wvNNKOls$7fgp|wP zlKD~U2lrJ!iC2Axk!qtpV@?|vu-l)~pyj=-oGI@jr=eWfOUrMtQDu`_BEz`qCt=^m z+Um7{s>t(`aC^^Z0IXNB1PB>Bg(J_Whumav%N%CEo}9ygQ5P^Xn8fVJ8i5z-@JbqS zDqvyM?4;cp5+jq6N`wGMZx#h1{j*6P1qHt=^le#kG0k$};5ENDmZ-yOoJs&HH8EB@ zQdnhw&+04NZ|SdAQ)#XH-|VvjarMH7S|aIJmUAUrV*zzF465%N%Lo|TX_4dXQS?hu zeR@oWF!J+5kQUS^K3`-XppF%(R=bF8SGcrWc2}}4Ks7KeEAg+?r<)ViN@VO#u0$_1 zC+$@Qo>@b#O9cfGrQ5)siZT4{pNkRL=$|Lv8>1lgw*slMAg4j9-3W`4tUzUFK`cs$ zw2>z_)!F{kcy47Z6!=WkDqHXf{Zhm*W1S*kKShh+_kF5Wt;2)4n*z|itYye>zJ)** z^lt2-X0m+@8e4YKbEpG$*EdH*onN z+7BA4Np%F$*cN0jx9-acHJgq=nfR(B>#ZwGDFdv=iY&^vUpKDmpjs03nO>tXSCC=>1sUV<>(VU@F-FP1|*J0xbYRY?*;IH$ALlMgn^A=$2Jh^&&2OlL0+u! z3fEUryoTV!gw%Pq3Z_WNN?-#PD+v1<7C$4>XKvWHL0i3%))gAm^`L>Mv4Uu6gT|{o zHNdzG79`F89PHmgFFD3d$lfpP-5mDr#OObaQ3&uL{bPNcV^~|+SSy$ajX_}pK1^>3 z@|u(d7IyFKYyuA%QbxAiK?MtH{hy|LOT4=A+I6NgBGB*MDUUEHOAaT700ja=(oO*{ z{qSBwJZ!urj~%UEmMU=mgj!|Up5)s5AvsAC$_IgXGmO?mIMq`O>3YNYdOt!?@k1H8 zIUyzJ<)IJf3K@NnU8cNe8PYF(cGp6iV4*Lk?%*T5rU39y*Gj5>d%U@`1#(IS;(Is+^=V%ceI z#sZXkvW(ivke8`*W_LlS1#h7gK#Es0innORuOO*uS@PnBLk8)FT}pfwU|B#w(!`r9 ziMf)ZqH-AqkQZD0s~(^WLA+%-dVueGBV)I^w<{O(*}1dg&A?P8BTtj3e&opwY$dI? zHh?$u=jwrt;y@}3P*lJVuwZG`Gek6C#ej)B76% zxl3pZkgHT3XtO}hs+1=>v?3NIOD&2j@jj+LVPxal$2f--VB@~}6P_Z5m1I^3O39Hz zc9+a!x#r&ZQCN=q}g`m=_3j1ZG>bVwv2> zmDgSHG)Fr1jOJ;w)mce(b`lFBIa{%}Tl~E6{?)?Rq)p~pXSFTqy<)Cz`UT0wu2=E8 zgYY_FTvQ|(_pYIBw{<8{0NjZMm$;DeV*QZJ+aVQMTmXU3lAmH-R4)241=jVnyTsFv zUrJdzjrha4H;;fQxn%JHMeqbeWb?8qDV`V@tYx{1vA-b6xt4eLtUU{xhfPptj$uYv zqCSJ3ES3ercj3cXnZu<_K${`iWJe^-uGW2&gXlrVQ;I0aj;GN0luJn|T1^}wAC0oG zgs}0dEY&;#$`fyfO5Y3^d;KTgkaqzKg2tz!(H;{tUe`~&eF6d!3wbw+j&4%OL~e#Y z2Yg+c`7g3(&_;eB4A+UD8!RE;9&NSggM-Gox_M2Cp4MP(p8hCt-aTQ{4`J>|3$vrp zV;!m7RchB04WRNWXz#;pCaTEDpg45)qxK29gGNCos-0Y@#B}G6A%h#_>bX#x9CPFh7}1C<8kL zMVDLEpnq;@wR}65U~OsvM96eL#AqQuupGN2id03LLA0HV_ZMP$Y3wQVy{D~yhr#fa zLQ2{OB~_`@3Yd=o7B3z7y^RR#?xbji8uWFxJ%wgQRnQ#DhB>+3$<4$#a0X`6Z{NUf z;!M%0XNnW8;XYuLDO%^k&1MVofxl3(ZQa*QF3E(rm}mjSxUr`bHw6nwclWy zA;(H%)TObI95^M@L4+k2US~K*=kGwKS&MHsdkH5bbX+uhP4wHmzPD%b0m;Cwo0~}T z4q9H=c-=<4&-{t)|(rr2!R&r4n&8=?}TbcFZcjQ3fE*H?})T0)Eoeoq3DIi5gCo} zt$_E0Uix;}*cn^>Xrh3f?dRIZh0LJS#8dnSYV(=sZzTYZj?hU z-It+YIlAPE@uqX6Ub>B~D0lq1MhwcYj&JoVx;HEu>g|GRKiN1W=Hq+rD8F5)X4=VZAXd*G2g-4m(ig?zLU4IESu<+kS?Suy{MSptaRo zk)CX{R*58Z9*~1{nQtDFx``v=JoG4g1d| z1y>f-H-WlxMqMBeP$0-ypl>M(cz0M^EoVh)oGcb9jjg@o?9~?ZuD9q55S;p}3nZeS zw!n(mYY!ELf)x?(jZpH$A9z7|$)$oq0#uL>?u*nXcZF!TtcIZK{Zt0;hfC>aVJFC$ z#GJ(Tq-2)Z2ErX^w5jHI}cs4VBm zq~es`VHeV?uub;j>(UDb9u~GPwwZ^?CH+02jXJdunPK_~YCJ9!1LKyB@w|Uw7N%~; zVja_`whn|j2-<*h7x(x(zD8~iaf=zbykko4lVi!9$E)Aao8s2wMou&!Q{MHjml@@$ zXUGs*;XJYPDx_}0(=j@kx?jsXBpiRQ{2XA*{|;sd=sHqmA>rBPcZSH;0^O}C6|sd^ z?k!3E-R$-3BP`_IO3!$omx)ojPcdaJ5u5i6@?~YOx9F1lA1(#5|Ko*{n!-LM z>D5-NqtZd?=o>)w>78UVsa1c4jl8JfCMtzuMoS-bf@gpX|9G|NZInSVayKW0NwDWc zRI7bdELAQ1Q8+>M!+u!^)Nqw1`%Ok z93=JW*xy?@)Zs5I#%BIll*!u#tiXrng_p>J7Xq`gZhhe)WlUdSl839?I<5+6BVFJ3 z_d=5bL`pYHX~jTe7Bn?{s|T7ChyhMCq)>09YZx^!+XL=NE&Ceqhs7+2#i5pxXAcAD z3i9RWQ#2QJ`AzXR;@N5epuiAMiZ+Y8T|t!%aE%1G0-?A}wgN1;%y+*4unG_cto=Q3 zBKv|q^J*>F|4ZSkaY-1fOqBZ^QvP=UR+6@%DiESqdkJQrOy{t|tK|rQ<8YDC$8rkXn3cHEAs>ll%OJ2Wd9PdL5Or#R3KCa&1->;gCc=EKsJ#; zlq>SH5}rjDjMO$oJsa%AynxfT&&P>o=k$D{)9D{4Co8|O2Pp?EY_-vL3h%eqzzoVe zhMzC=j$Ozee4-_o*lLTzvH>40S0c@UAB#mp9zw9ZJDZ!xX@#B>A@&UBBc61b1>Wz7 z^Yd@*VA6Q*8s%NLo}U}|;78s~YxyZ%$?B^64|ntK z<<5G2F+O>`y~>kIieCD9<);p(!?8FWv_GKJddO(NDlUsRjI8HU=w!T_@&WTEd0Ae) zntYHoQ2IQhfhXH|g)4uPKf!Xz0hvh}rW)Nn2maPe>WV)AY=N3wenT}L?7P&R%ur3P zdZsEXP~%bQc|z_q=nfIe-YhFrlc&mz=q;0%EHgrt87*ZnPNWPG6c{aAdbKSwB-jK5JOXm0#W$1+k zifVCa$5)Mp{xNVGH9Fq5N1lBI4+QYo^08a)_Up46J>CV1qkEje$CLDx0OtGk zeM&UjxwK=_V-e*bG*g?|Y9fAL#q49Q6EyEi&j;2&_&+|L6@T}5?it-P9yVD#otM-6Z7iJ{ zCf6L*FgXd6H4_UqVKnO*X2>kzK9+IQXx4bzCqd(O4hI(K5U=rk1t;%10BqU`p@ju( zTZIHpLV9r}5NO!Fi+q?a*3R;^49gn4K@K=_`+ltg9Kpa_tidKd#}fj42;*Nb=W2&| zg~UBAeK6vQoYG`$$k?06xsi}0KS^@_aU;1u8Hp|p_2{re4%g0q95o+eGtL} zajY22Q)jvvk;hkfyPu=SHDHp{#>ucbbQQ=o6I3k96%S}vG!sG9ek}K$kni;3ZcNCW_Gz*p+9k@ePal< zXw7n^KR>0*w-qAxnuOGvpnCjItp|@w{8!dP75~qz2SxwySPz>0N7rMWx8HhXJd<3G z6@8ZDQI#( z|IzjNWO%>zISpTAQG^->>^nrpTgE9KHj_^<9c0Zo3rg3P$qgLQ&ld1G7-R|#GY}u} zAOb?)z%0%*D)(U|W`CBXOAfZIyVqglD~`f1zxXntJWaP~caBXUH1fHU(q_!iIaP%N$0IpdcOFbWQ3$j#D^W} z$ps6Qz8*roZ3+Q}z-Nv{9@E9v&pvqbwq9rm*obmmi#A?=iVy z5%zX-z2bUv=zX^Rkf$0#8@Q ztTLT^r%?iuyOWPL*2!&IJMl^qW9GFz;Y*Kc6L`;bl8TT5$Nbs^EQm zWHoqcS5Gy(K&V zHd5Zkuy;$)+o86EDdu;j6KocQi^|chHer{va72;=XLoB8_-JO#XvfGwo6uw^(XhNx zmc^Z4qx1 zTL3~5V@Xszea(5_4CIf-nLUEk^l1(DeY%h*T|OvQd1x;~lkeYs*qNHYN9St18vxL& z6Xh2?H)kX-Tju1_v`&YSiBwY5^&ok5(ESikg<&eZtvi{xWq{`Jx(Pi4j5x5H8;A7YB{B5aJE zL;6j!~z@>(#Jk7-MY!wzxFk2+KU4CAp|Dgn0o*I>UiIj~FB zAiq+B9kOar0e_c3cI@=x_Pde;^f76PgY-51ualBD0I~srVFS5~r@MS%ljR$_y1cVm5ehZ?qI=quW(uyG@#UmgB z@6Jm8v`y8Uv|64o2mIW_eoEdTBS3)E)HTwTGA(T2VW&I_J&_)|`AVXM>hCHbv{pvR zS(C&x+{Ga&qn&z6nnqJB&r08QKEJ31RQz3;1lsMu!c_E>YIB2K=l#6+1|F{xDJO5c zd^_M|{LNaqwyt_<#Ckqn=WDOf7`+>cA^-C0cvRO=!F2)CV@jOpfikC1Ra=+QYP84i zry^zQCNGK$pstXS3seZStk0zg#v9kS>!lb&AD5LJ-A4`ip6Gv2SV>Fsm?3!t zQWSxidoOl4t}&e+QYL$5hRtW?l}Jg+X`utUIrgK8suK;t{0hP+ z_1`iM>6pn%2PrTd8ggX z{C*zKFvt@Te%}^t*^_w2na;2KeJcc5v=t9Yig$~AQfRlq1IC$C$RGcKDM}3MRyY=s zj~TpsvPL$fdhESazH^!+^MY)|#;^MtBSA(KWZ;6czzvr<#gWY1y}r0#2GfD$D;aRe z5YHere@D}bLyRKt_PG=DOxg_vAV(ddl*BBZi#0yp;^8O< zNtBzu|0L=h0Y$^@oy2px3I_RxoUe_~MVOg0z5yJ~Lpj;I&ZhK4)-QBH|7h5rtgf9p z^0ZVQgq2h>Nm)0k=$rHFs*h_`TUbzK#{DBah_yMt|0l2pO?-eSS|+YY`X7{>J{5{djBSDv?cn0!zd=;(8Q&~Kb2 zGN<3$n5a+jcl*w(KxKO6Lqi};i!Ubo5OBIbJ?Woc<*Ya$Wrm(jnNgH^Bwfl>2}VJ9 z`sL?yNk|R6D(X|&EA}$pD#dh#bQ&u>)Ztx`%de1860v0A2vU1rzM?A+O1&;jfjN0> z1bG$?ZdxI(YKR9J*(d^CmwKf1)Xmn{Vmej=%mQ@JBL~LcB&0_y*mMew)hnCc<*kVz z+ekgai3|9%iSEJapsxHvfcfRM4SuUUOKC|Ss}SxfPhLEZD~#Kc=aOQcCHd*lJdp}1 zh+rp{d#!}f>F>pnuj~7TSAiBK48;stbjxsm@c(9ZU9iN1ww+{&!2Zf*KhK$dGrPzYRHB-!()S$k{>Y(SqeTx9>*oo` zVTvwaZ*LY!Z!l=$)O~YM?$qR~Rgpn*`U`l^^4u+4eyP9|hr;vZ(^?gLjmrA0mTq33 zuC72__5d0B*smIa$GW3_W`Qr2EAJu8>9ic{-oxub--$(&pxK{+Cd_InzIVu+pbt2weC3|*5rJIHbApuLn&!v@k z2Sl_d@jl^0$wackUgItOGr)@aWI!m1|B?*GeM&@jp6@mNY5pvw0r7IVChGr=I zu!u;=HR?0~x82vK)xNFP>oq!)OYRUS4P@@aA4KUP8-QuaUfm}Wqr|H3LsLyNC@G@D z5a_`CFGbVkvY$I5xn#iw^Y{>q8>+oY~A1SRv?BvtMy<&*!~T?_mDBxUh zyvWS?D$HcfvP43eACR7BsYfjMledL(4GzS2D=_OqEQyYNy?`RqC}KoJPmClRb^Vz* zBO>b(b^R8`XP5N=MaER5T)q z+Z(Ft+0&~(k7jIZ+Gm>0=u=6q{{#JB5}4P)M|aq!;EvUv)i zx3jrcZ+tDQg1AL1ySVH_;z|UAXbR7g^XcJAC&IxvBaph3vu}TNsRO&-afUOMuMe~9 zO{Dkc3Oc76*xw~kZymAZnv|6PVzhH zXu(k0?K6U^)W$V@YeIcP+3sh%)z5E)&1JcR`_ivuf1N{m2i0L^zD;Imh|Ew`>JV%= z`ZuvwVyuZ8f~iZNiCSw1nJ871V?{~Lu!3vtpxc^8nVp|7J2P1;H9LE)Vb3BQt$f!C z+^Pa`E6}@~OvgXd$8O?#=#R8m#R%=r+H2?3WbM?t1$Q?u zYktN>tJ0p@mt4=N02ZGwK#z_Mskn{Aow#7>SV@s5bE0EMNHXXOs;Ym+y&^P+%*=cej7kxh*&jfmT=Tyo z?2S{&teo?%O-~CM@|uLpjTdW=sA~qEXpT!#qOMfSxyW+5gDUa@D|FlnsXC&rPAimU zr5&_Fg9ugc(5kK$F##(XGa{cWL^-a`PnA9dqAqM+J(Mmg4!$?2SZ+<~BftN&la!qK z)TNDTS(rmNGiOUceWKjmlfyMx<%p>#!85NRVB{3?Ykl;JJ;#00hZn#~s>{6od_-3> z=Z)Ed3kALMACx@>F-o3Glw0LIWvt#MOuuW27>v{`JN7V3me!Kkmv9}@)6+U8BwTTE z|0UsiSKKQSuD#-pOt{_<_ZtaUySQIXxLy(W+=Q!D+`$Rg7IDu?xSDZ|oFDVc!{-ou zP`-Y_xiaR(#2pa%uLnLQ_K7dc%CU$SyKa-B^++l3Rl=D!6F!PK+%9W8osGhDWJ>ii zWQ(ls_ei!&=1Wdya*B#VguFO&go^rnsnNZqTz0A9y`@fFqrPkTxwcY!OTDJDWMzJe zOJAj})-NdaiprwK_Dj3e)}E~DIX2gGy;*8cOZo-jhBZ@v>~MUKzaQ{7pTB$fTgKli z{(i*YkNLB(Bl+9QPjz2r8>etb%FoebG50MeVtgX9JoQL}9^2$T@KBm6C_E7Ec_q?$ zS)Tlyi=A58z+P4u{|LqcyFUIi_J;9Y(6IQ&{J;din=MY}H8}AW^!dD7Iy`=N)N%|9{ zH@Ti3jl$Q5PX zfU0EHe@UomTf)`$P5UX0)MSi_j2$HXEDyvdF_`#K)+xRp{t+2=6l+~{aKzI6ztYG2 z9R;hl$5Uv6DH@>GthYaka9W-Ciq#2S*_$alGy8oec1N;61wo_JILQ+6g*ffXoMRjY zE*X$tcc7E@xK9x2O1Y~L0VRXc^L5hlf!xv=EvwU!oyhs!Ify;&q7wxWs-7X1S>tEIk35lF5h^kJM zx%ikzIeQkn%@KXtEaOEZ*A%N{`Pm!NU~Y^Ou;D)%NmF-(^@UamxgacInQutZ1vJRqN;4|q;s zck6IqK8*#6|B8^@PUF*Qu7gB~jpG<(bb9N$N5Y0{r#MkpV6>I90KZODlk2O*NUKe* zA^2n|n_OSFed~cWhkkpVAlLa)vdNhuE%(M7nfG81MlYSY$;cGA`Ltvt1rNCCp{S=A z*BD{n1#->^q#;Kqavp|o=*Azrs5Kv}(mLHlHNzYxaxRn<279F*ndKQn7ec%P$?K;x zLp(3Rw6H_nD3S9dke9znnS>>Bjv(bEn)m=?#qVY5?2V*Kyiqs!h`P`qSK~-3f8m=y zeftuzX3>2OFJQ zOYP7LGxGz&2i^kBk@FAZ=QQL{Ui`IknbdSo{C(QNBN7rD7M1oenVGx`XX}P@7)wV} zdU}V8yNhMn`E{MT_WR8BR8;=qH!V8;bV|nwp-ocn46E#b_@ALf9bb-LLl{z6VMRN? z$vH~AoWRqVcG94ffuPHqrV#W8too95-A=x$x^gLWPJFr*7!bb^PsgD?<>TXtiT?{f zcBGWI@GbeqtBrIR4|WRP9f+@o`avzu<-DdmOA!Oz*ve;@5;@;s-qb6;7*@NR4 zJLS865N~4?kJW}YJzf2QKfrPt?6_ya4?NM<=7ow&=)l%X_p+_A*9&%%76 z3ldcHA?i9xaHH!bepA$p(*^aqc>E-dD>#7V#ny+XvMajMg~fNG{BFH8vkngob&)t} zEtOYJDg=gRtRDnbxaCU!kn+hPZ@u=cKU+7yJw#7y#fzReV<~3(EqXND6ZEx}4Kc3G z;C0yf1NqQgS}f$Nn-77j&+B-bb9R`HKuUJx9*<*@_yz)(XW^zQFdfoh&G)L^@fVod z{2k28psGFP1N0R+2ZcVVskHJe9s9O`{i@w%&Z-^d8S(uTfLHFpNe)oOM;L$sZ%_;!aFoo zb#=2OLI5Y}(Q0W%I-(-|>(@%FivCxxlz#q__0bKh1pIj>TzgUu(2F}+NPZ$`5Ou=b zg>z6Jf|za=c53%CApwsrjs6POBdrxAavoA#s62z2PdD|n_+Q{}Vu#YoT%ib;DHF32 zg}(}Gb@Kw_94S7w3a8^7Bq*7Hvl2OCtRbKA(0y;u=XDd|n}VO#IwZ@^u*w#lR#xmc z&Q!J@0G77h>S<`H#GPN4ze)RPz=(10KVWS3S9Z=Vn?1*0dH9;ybISw94x^KM3)t!u z4raRR<+uYf~sMAw8sD*l*#wW~tdUUcUqkNJc$$Tu22^-dVbwV3kcUFp{EN|@0 zvr-*p7ml4L&iSsVKj}tJ%Du~@qq>v-bW{6TY(aLwaIJ*O`y3?X+2rKSbe{wipfSfv_7aYP%+E*6L<9FzSA5eWts~+2*s}E|G*VJ=GbjbaB!#_8aPc&RF zlRMI!-sJiX9s%;G>(}`F#~X6XMm`Q*5AU#|<$$6qZl-9-#kI+SJ!P16njcm7WjCaFAang?m zQqr`tLE4{jBYQhTY0aU0n%Q*Ifd^1-$#Cp{efD1fVF&^!?~JC0^Y?@hbB6F{Sy&sl zb9TrWI?PQE`QXu!1?S!3uiP)DkPka}^vu68O+}Y~6f!8yd_pW6-A5V{!=kKiVwkLP zV%X2s@3ZRn-}(Jq`-!~;Hwt&rjf1Pg1%hMK4m{0)*p{B?_yxTDzAB8^C~5ciq#?*2 z9wuX|U!Fy^{CGs~_%GdVlwEJU5jCcn4 z|Nr~%nt`r5tEO!bJNXy4-EP|*(qP43VY}Db?sVI|$9C7)?k{Y&&USa%?(=qiR&5SP zZp`wHvE3ruJ!t1o=6lkPf82JH@!fX5^hPV@m>o{F!^wPG>~epw-HCQTuCU$nZMVx# zf6I1Xw%ues%k6O4Y4Jn_Wb#m_U7*w|IIIm&+m=@ z!=|=R>RVoUY5QAN+=83$m^WwkjN9hUD=(WdxBQOp&7Oa0%V#gYx&C;|XT7<&Z2$Ru z-#k;k^0{h2x%2N>@Xdd{`v(ig4x6PKn!Qj}pA0%?-CTC_j5)LC%5WH^kEELQAPj_^@f9h9Z=N4>>de1F0ISq;i{3P(>v}(<%Z) zjg(3j6{WwoyXWjVKvh-zfts=2y*F>(ym|9xc6Q$Eo^M`|a~Jz@_Rq(kfBnN3P9FKy zn}2EWteh`6Gd=x_KR$o>y*G~?`Os|t*XPqh4<{+)gI zw@g;w{r-;0M_Tm!!IlSq#_4Fw2Rpdr6(j$;R)=W1rB_RD82Oo&RfT!aKQa7n%e8Cr zrQ^=`TE08=+wt}n-fuart@IzX;AkG{LqmSHMO5lHbiXod=>5pZQ!Cp40nHjs?J%5A!(Pq1AwsO_*sj(5cp? zelF)WZUBtF0C<8qxIr3ac=|#(6{K@0JGY>WHw~?*JcqKm1!ap-W={N8+n14S#(J_) zck5w&ed#dp!g9^ImoUG4Mt9Gqo;^o%->mrNZ??SbTlDUkSF1bNHJh&49grkHUpD?w zG`f49NUitm?iQnBKoRGeE-BP+m|6qOz^MdqeVea~uvc>8tlOoEDYZ5h=Q8J0Lsl`|SkUvbUj$CecFg!ryMIPHraQugr^!hfJg+8~%H(Ns`!jexO>QKUr^(&RJnX7mGWS8B(_@&UdcJnw zzI~y7bb~fvr>^xwR)e*j8#R5c8N8b`eH~_=PnYv%@N~Id;PEqJS4wYp<|V8MXvZb$ z`Bg6y!NY0aHiD!v@G36yaN2}TIC!Qp@Gy_}G8?c67~`^@c{B|l1G#kd)Q5aWi7ngJ zuP9thv$pJ0Tt_kl$euk0wo6vzV6D4>MaIDEu*~x`o0$JaNhq{Zp_)y(p)AVr2voVQ zkiIsugsM};R5@5e4q+7)%;rtorxr=pz8tT`jk)(E#sNxesx4G~K94Nt+%&s{s23A* z5Pqv^$ft(6Tw48BKGmEopvuX`v}B@?az=|ZnU^4UKg&S}*D>eKdW2;bTGm}ImGzan zE89w_abkk%N1mirsi&xR@R#KD^b1a5mry)gG_!a*e=1k9_u0IdzNZ?ORJ|*~wxmo-85zghMNTwiVY4%RpB~9bRRjmr##Tk5G?Lk5G@$7NIRdTeP4p zp*o+c)dH#x0sHc(+LKGw-AiXHX3D08<$1I`WT)l6MYP;wrRB5BW-6!4r%ENe#=I^C+)NqzctrBkw?v=`Lu4NfZVCYw0f|RRthy#JzF)ibh=`yOe*bjcuU+h z2;;4DRvPmWy}Aef!?RWHk2zmilTC$!H7m=l``3wX30)5A8qK1sN3v;6%7QV;A!n$R zoW2r_O))u-RLw4(shBRCa!5i|K2@RI;VCD_k<8JkDYsHN^el#+9O$9jh=ThONf~yS z^Fm<`?5HAb9AQh1EsJa?mXh}_qATvk8i3yntJ#uITX0y^j-PZ}f1#Y}&Q(y=*-Enc zmT58}$W^eM!$OV`8`)BJVxD7!Xbtn5t<;ReR_BD3tfPxG{$t-K@^Kmb!gA((MqQM% z9rJA#N>y=okWH6iZ&e_OvqEO@SL7C;aZZFH3^X9rjMJ`o@06sfacx+VB=$I{@ zDUvihufrJUS|}HDEw|Asp(`W+mXzA4RJBuSXc3j7th8~-%=Co5?|Azm{IBVUNxK)Z z{4=1Bn(~-JWNpmyE-~p%*Zmvhavs5BdECc1T?P7DQ{KMRN=rS3v{WveaY!Y7T#xNZ zLgwa2iA2<6thLddg>T7WZG(-4u(7Z)PZI0`+51s$vye@;NZEZ^Zo?k8P+*|~kDUq{ ztzNq^Mrr*62Z=rc9Dsht0$!8M@&Y?-Hrd z+hW)Nd$sy*?jdMy3rhnh-smwd#yvxm1I^fmd_JHEAmP2kD}ag8I|>)J7kUQUbM1b^ zrJRai!N(!Qd{dm$Q$Khq@Mfmc9IRij60JH6Y~rQB8-v`ai8l(~40w`>S9Ai)8hD?V z<_y`(al7uJ|2A&-T6QEwdDtt;;e;Fu#Dij6B8jtHnYOfdZ)@+ms!MfBTtP%Gnzl&7A56qziMW3#EXk3$8pggSEQ=!UxfBaTqlqBV zdO~{<6{g1M>Wj2rM8M-$#6f>J5=9~Jj!_#59^|})lln;sl$y~g!KB8j|xy>SHEZu6fEg-4rTU!D{ms06Z%P^oZ)` z7BA1bUR2wXvJ6jo?CHYP>p&H{6YXvi`;!9$qMUB8 ziDzU`f-iarTmE<>-AloQLdAj-iBp-N?3FJaw^%?OG&}wCmZQu3uc!x3-|YND`0S^j zrr%&l-z)k4m<3qtG&(k?W9FMvk^`2@>8tC3BAiz(!5#&1qd7)2$B!IGK7-KeX~-}> z1vm?u@fn0#=eRC#JA(8JpuNDIjc^I#H*@U9ao@A8XbXJCr>`Tr9W>*=0>(fyKHi1x z6==p60L-VYL?7cs@I2GoiGH^O`*6fD)4-4TblMzOalCapiPJ^MFs{KpPXg@*{`IXm z;N!Z$90T1C+8hgUjMR1~(c9oN-f|a0PSECf!yJonOp=aq%rOkdGM$J+qKG9J-vk%| ztzpokphtiY046{)J`9)yZH`wsj+tfvpYe+O;B(OCc*7iva7+^Y5mD7~9p3?Z18BzQ z03D!bfw%tzV*%O=yaynG=6&$TxTaH}-47A%0E~e40Urdg4C5CcCb|doG2j-&3Dclk zft5!w7B3O0z=r`I(9Z#%2kZjP_~;nU@jxE~t{=ziZlK-3Zv*;3(_=)-0Nhp;aIZn{ z0=~zf8IK$ELEuvc&G;RIJ_o$%=NMn;WUK;MC*u)=X8d~q+jbV%e^96Ufad^F@EKP< zuJakU8}u&V$8erI0hxoqGXVA*V>}nqXeaO_;;Bi<@cB+NfNf|6J^(lc{vluiG0WEejSxCiwAp0czvOeZc6T*9>B;<>n?T7L<_ z`x*Q!NFeOqZwSuITWpswQHFTYLfC)c+Q!-139f9U!EAf>w@o*h6ImXV?4%y@ zqz-w_0Oks!lZ!fbqFjd5#kvjTf{YI9VAVBL0D114s>#NoHEObYFAd>OhG#?IM^RJ9 z+@TwAYA#S0>J4bMxaSi3%$^&-$YblMc_WkOq*dVJKVZOSoTF==!`Do?BaktE7TX~fpr)2oEb1H*Wd%V-b6tbW zUFQ_z!9*w$A84-Y^=+=-Q0G*zEe{2v2&tOuhDD{W<=TSWrhuY|vHs|=6AI!=b6rx7 zU!&krZY-eG$09*Fp(Mg;J>te|0!qv^)KKR{I2#Eg8r^Ab4XT{ZCRI)Ato9hBf zXM8AeizwGQlaY-<4xyUs!hxtF);ZVC>uFm1`K>gq&9JFy?R@7@y=iUQZ^-ZfTuz_u efkXPUmDcf&@zL?I@$-+<6E@txE~ozw5BwXUNyWYZ literal 0 HcmV?d00001 diff --git a/influx-data/influx-target/src/main/resources/static/index.html b/influx-data/influx-target/src/main/resources/static/index.html index 5d97a22..cecab50 100644 --- a/influx-data/influx-target/src/main/resources/static/index.html +++ b/influx-data/influx-target/src/main/resources/static/index.html @@ -3,7 +3,7 @@ - 迁移 + 数据迁移 @@ -35,15 +35,15 @@ style="width: 360px" > - - - - - - - + + + + + + + - + @@ -149,15 +149,15 @@ checkAll: true, tableNames: [ 'DataFlicker', - - - - - - - + 'DataFluc', + 'DataHarmphasicI', + 'DataHarmphasicV', + 'DataHarmpowerP', + 'DataHarmpowerQ', + 'DataHarmpowerS', + 'DataHarmrateI', 'DataHarmrateV', - + 'DataInharmI', 'DataInharmV', 'DataI', 'DataPlt', @@ -166,15 +166,15 @@ ], tableNames2: [ 'DataFlicker', - - - - - - - + 'DataFluc', + 'DataHarmphasicI', + 'DataHarmphasicV', + 'DataHarmpowerP', + 'DataHarmpowerQ', + 'DataHarmpowerS', + 'DataHarmrateI', 'DataHarmrateV', - + 'DataInharmI', 'DataInharmV', 'DataI', 'DataPlt', diff --git a/influx-data/influx-target/src/test/java/njcn/DataTest.java b/influx-data/influx-target/src/test/java/njcn/DataTest.java index cfed52d..e4a7140 100644 --- a/influx-data/influx-target/src/test/java/njcn/DataTest.java +++ b/influx-data/influx-target/src/test/java/njcn/DataTest.java @@ -6,6 +6,7 @@ import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.extra.spring.SpringUtil; import com.njcn.influx.bo.po.InfluxDBDataFlicker; import com.njcn.influx.core.InfluxExecutor; +import com.njcn.influx.imapper.InfluxDBDataFlickerMapper; import com.njcn.oracle.bo.param.MigrationParam; import com.njcn.oracle.bo.po.DataFlicker; import com.njcn.oracle.mybatis.service.IReplenishMybatisService; @@ -18,6 +19,7 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.temporal.ChronoUnit; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -27,7 +29,7 @@ import java.util.stream.Collectors; * @date 2021年12月14日 12:55 */ public class DataTest extends BaseJunitTest { - private @Autowired InfluxExecutor interpreter; + private @Autowired InfluxDBDataFlickerMapper influxDBDataFlickerMapper; @@ -39,23 +41,42 @@ public class DataTest extends BaseJunitTest { // LocalDateTime endTime = LocalDateTimeUtil.parse("1970-01-02 00:00:10", DatePattern.NORM_DATETIME_PATTERN); // LocalDateTime startTime = LocalDateTimeUtil.offset(endTime, -2, ChronoUnit.HOURS); - - MigrationParam migrationParam = new MigrationParam(); - migrationParam.setStartTime(startTime); - migrationParam.setEndTime(endTime); - IReplenishMybatisService executor = (IReplenishMybatisService) SpringUtil.getBean(Class.forName("com.njcn.oracle.service.impl.DataFlickerServiceImpl")); - //查询数据 - List temp1 = executor.queryData(migrationParam); - List collect = temp1.stream().map(temp -> { - InfluxDBDataFlicker dataFlicker = new InfluxDBDataFlicker(); - dataFlicker = InfluxDBDataFlicker.oralceToInfluxDB(temp); - - return dataFlicker; - }).collect(Collectors.toList()); - - Object args[] ={collect}; - interpreter.insert(args); - System.out.println(1111111); + List dataFlickers = new ArrayList<>(); + InfluxDBDataFlicker flicker1 = new InfluxDBDataFlicker(); + flicker1.setTime(Instant.now().minusSeconds(60*60*24*50)); + flicker1.setLineId("12345"); + flicker1.setPhaseType("A"); + flicker1.setFluc(1.0f); + flicker1.setPlt(1.0f); + flicker1.setPst(1.0f); + flicker1.setQualityFlag("1"); + InfluxDBDataFlicker flicker2 = new InfluxDBDataFlicker(); + flicker2.setTime(Instant.now().minusSeconds(60*60*24*24)); + flicker2.setLineId("12345"); + flicker2.setPhaseType("A"); + flicker2.setFluc(1.0f); + flicker2.setPlt(1.0f); + flicker2.setPst(1.0f); + flicker2.setQualityFlag("1"); + dataFlickers.add(flicker1); + dataFlickers.add(flicker2); + influxDBDataFlickerMapper.insertBatch(dataFlickers); +// MigrationParam migrationParam = new MigrationParam(); +// migrationParam.setStartTime(startTime); +// migrationParam.setEndTime(endTime); +// IReplenishMybatisService executor = (IReplenishMybatisService) SpringUtil.getBean(Class.forName("com.njcn.oracle.service.impl.DataFlickerServiceImpl")); +// //查询数据 +// List temp1 = executor.queryData(migrationParam); +// List collect = temp1.stream().map(temp -> { +// InfluxDBDataFlicker dataFlicker = new InfluxDBDataFlicker(); +// dataFlicker = InfluxDBDataFlicker.oralceToInfluxDB(temp); +// +// return dataFlicker; +// }).collect(Collectors.toList()); +// +// Object args[] ={collect}; +// interpreter.insert(args); +// System.out.println(1111111); }