diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/event/cause/jna/QvvrCauseDLL.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/event/cause/jna/QvvrCauseDLL.java new file mode 100644 index 000000000..7e560a4ff --- /dev/null +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/event/cause/jna/QvvrCauseDLL.java @@ -0,0 +1,132 @@ +package com.njcn.advance.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, "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/pqs-advance/advance-boot/src/main/java/com/njcn/advance/event/service/Test.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/event/service/Test.java index 4f58c23e6..2259e6b46 100644 --- a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/event/service/Test.java +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/event/service/Test.java @@ -1,6 +1,7 @@ package com.njcn.advance.event.service; import com.njcn.advance.event.cause.core.VoltageSagAnalyzer; +import com.njcn.advance.event.cause.jna.QvvrCauseDLL; import com.njcn.advance.event.cause.model.AnalysisResult; import com.njcn.advance.event.cause.model.DataFeature; import com.njcn.advance.event.cause.model.QvvrDataStruct; @@ -30,7 +31,7 @@ public class Test { WaveFileComponent waveFileComponent = new WaveFileComponent(); EventAnalysisDTO eventAnalysis = new EventAnalysisDTO(); WaveDataDTO waveDataDTO; - String waveName = "5"; + String waveName = "11"; String cfgPath, datPath; cfgPath = "D:\\comtrade\\00-B7-8D-00-FA-44" + File.separator + waveName + GeneralConstant.CFG; datPath = "D:\\comtrade\\00-B7-8D-00-FA-44" + File.separator + waveName + GeneralConstant.DAT; @@ -41,34 +42,64 @@ public class Test { throw new BusinessException(WaveFileResponseEnum.ANALYSE_WAVE_NOT_FOUND); } waveDataDTO = waveFileComponent.getComtrade(cfgStream, datStream, 0); +// // java针对暂降原因分析的调用 +// QvvrDataStruct qvvrDataStruct = new QvvrDataStruct(); +// // 采样率 +// qvvrDataStruct.setSmpRate(waveDataDTO.getComtradeCfgDTO().getFinalSampleRate()); +// // 瞬时值 +// List> listWaveData = waveDataDTO.getListWaveData(); +// // 通道采样个数 +// qvvrDataStruct.setSmpLen(listWaveData.size()); +// // 获取ABC三相的瞬时数据 +// // A相电压采样数据 +// float[] smpVa = new float[listWaveData.size()]; +// // B相电压采样数据 +// float[] smpVb = new float[listWaveData.size()]; +// // C相电压采样数据 +// float[] smpVc = new float[listWaveData.size()]; +// for (int i = 0; i < listWaveData.size(); i++) { +// smpVa[i] = listWaveData.get(i).get(1); +// smpVb[i] = listWaveData.get(i).get(2); +// smpVc[i] = listWaveData.get(i).get(3); +// } +// qvvrDataStruct.setSmpVa(smpVa); +// qvvrDataStruct.setSmpVb(smpVb); +// qvvrDataStruct.setSmpVc(smpVc); +// +// // 暂降原因 +// VoltageSagAnalyzer voltageSagAnalyzer = new VoltageSagAnalyzer(); +// try{ +// AnalysisResult cause = voltageSagAnalyzer.analyzeVoltageSagWithDetails(qvvrDataStruct); +// eventAnalysis.setCause(cause.getCause()); +// }catch (Exception e){ +// log.error("DAT文件分析异常", e); +// eventAnalysis.setCause(DataFeature.CAUSE_TYPE0); +// eventAnalysis.setCauseFlag(0); +// } - QvvrDataStruct qvvrDataStruct = new QvvrDataStruct(); - // 采样率 - qvvrDataStruct.setSmpRate(waveDataDTO.getComtradeCfgDTO().getFinalSampleRate()); - // 瞬时值 List> listWaveData = waveDataDTO.getListWaveData(); - // 通道采样个数 - qvvrDataStruct.setSmpLen(listWaveData.size()); - // 获取ABC三相的瞬时数据 - // A相电压采样数据 - float[] smpVa = new float[listWaveData.size()]; - // B相电压采样数据 - float[] smpVb = new float[listWaveData.size()]; - // C相电压采样数据 - float[] smpVc = new float[listWaveData.size()]; - for (int i = 0; i < listWaveData.size(); i++) { - smpVa[i] = listWaveData.get(i).get(1); - smpVb[i] = listWaveData.get(i).get(2); - smpVc[i] = listWaveData.get(i).get(3); - } - qvvrDataStruct.setSmpVa(smpVa); - qvvrDataStruct.setSmpVb(smpVb); - qvvrDataStruct.setSmpVc(smpVc); - VoltageSagAnalyzer voltageSagAnalyzer = new VoltageSagAnalyzer(); - AnalysisResult cause = voltageSagAnalyzer.analyzeVoltageSagWithDetails(qvvrDataStruct); - log.info("DAT文件分析结果: 原因={} ({})", cause.getCause(), getCauseDescription(cause.getCause())); + // 暂降原因JNA的方式 + com.njcn.advance.event.cause.jna.QvvrCauseDLL.QvvrDataStruct causeDataStruct = new com.njcn.advance.event.cause.jna.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); + System.out.println("暂降原因: " + getCauseDescription(causeDataStruct.cause)); + } catch (Exception e) { + System.err.println("调用DLL失败: " + e.getMessage()); + e.printStackTrace(); + } + + // 暂降类型JNA的方式 // 创建数据结构 com.njcn.advance.event.type.jna.QvvrDLL.QvvrDataStruct typeDataStruct = new com.njcn.advance.event.type.jna.QvvrDLL.QvvrDataStruct(); typeDataStruct.smp_rate = waveDataDTO.getComtradeCfgDTO().getFinalSampleRate(); diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/event/service/impl/EventAdvanceServiceImpl.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/event/service/impl/EventAdvanceServiceImpl.java index 3899452e3..d82186600 100644 --- a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/event/service/impl/EventAdvanceServiceImpl.java +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/event/service/impl/EventAdvanceServiceImpl.java @@ -2,6 +2,7 @@ package com.njcn.advance.event.service.impl; import cn.hutool.core.util.StrUtil; import com.njcn.advance.event.cause.core.VoltageSagAnalyzer; +import com.njcn.advance.event.cause.jna.QvvrCauseDLL; import com.njcn.advance.event.cause.model.AnalysisResult; import com.njcn.advance.event.cause.model.DataFeature; import com.njcn.advance.event.cause.model.QvvrDataStruct; @@ -88,36 +89,26 @@ public class EventAdvanceServiceImpl implements IEventAdvanceService { } } - QvvrDataStruct qvvrDataStruct = new QvvrDataStruct(); - // 采样率 - qvvrDataStruct.setSmpRate(waveDataDTO.getComtradeCfgDTO().getFinalSampleRate()); - // 瞬时值 List> listWaveData = waveDataDTO.getListWaveData(); - // 通道采样个数 - qvvrDataStruct.setSmpLen(listWaveData.size()); - // 获取ABC三相的瞬时数据 - // A相电压采样数据 - float[] smpVa = new float[listWaveData.size()]; - // B相电压采样数据 - float[] smpVb = new float[listWaveData.size()]; - // C相电压采样数据 - float[] smpVc = new float[listWaveData.size()]; - for (int i = 0; i < listWaveData.size(); i++) { - smpVa[i] = listWaveData.get(i).get(1); - smpVb[i] = listWaveData.get(i).get(2); - smpVc[i] = listWaveData.get(i).get(3); - } - qvvrDataStruct.setSmpVa(smpVa); - qvvrDataStruct.setSmpVb(smpVb); - qvvrDataStruct.setSmpVc(smpVc); - // 暂降原因 - VoltageSagAnalyzer voltageSagAnalyzer = new VoltageSagAnalyzer(); - try{ - AnalysisResult cause = voltageSagAnalyzer.analyzeVoltageSagWithDetails(qvvrDataStruct); - eventAnalysis.setCause(cause.getCause()); - }catch (Exception e){ - log.error("DAT文件分析异常", e); + // 暂降原因JNA的方式 + com.njcn.advance.event.cause.jna.QvvrCauseDLL.QvvrDataStruct causeDataStruct = new com.njcn.advance.event.cause.jna.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); } @@ -157,7 +148,6 @@ public class EventAdvanceServiceImpl implements IEventAdvanceService { } catch (Exception e) { eventAnalysis.setType(DataFeature.TYPE10); eventAnalysis.setTypeFlag(0); - e.printStackTrace(); } return eventAnalysis; } diff --git a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/event/type/jna/QvvrDLL.java b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/event/type/jna/QvvrDLL.java index ddf9fd9a5..9127e012e 100644 --- a/pqs-advance/advance-boot/src/main/java/com/njcn/advance/event/type/jna/QvvrDLL.java +++ b/pqs-advance/advance-boot/src/main/java/com/njcn/advance/event/type/jna/QvvrDLL.java @@ -31,11 +31,8 @@ public interface QvvrDLL extends Library { libFileName = "qvvr_dll.dll"; resourcePath = "/qvvr_dll.dll"; } else if (osName.contains("linux")) { - libFileName = "libqvvr.so"; - resourcePath = "/libqvvr.so"; - } else if (osName.contains("mac")) { - libFileName = "libqvvr.dylib"; - resourcePath = "/libqvvr.dylib"; + libFileName = "libqvvr_dll.so"; + resourcePath = "/libqvvr_dll.so"; } else { throw new UnsupportedOperationException("不支持的操作系统: " + osName); }