diff --git a/pqs-device/pq-device/pq-device-boot/src/main/java/com/njcn/device/pq/service/impl/NewStationServiceImpl.java b/pqs-device/pq-device/pq-device-boot/src/main/java/com/njcn/device/pq/service/impl/NewStationServiceImpl.java
index 5ffb6f67b..7f24eadf7 100644
--- a/pqs-device/pq-device/pq-device-boot/src/main/java/com/njcn/device/pq/service/impl/NewStationServiceImpl.java
+++ b/pqs-device/pq-device/pq-device-boot/src/main/java/com/njcn/device/pq/service/impl/NewStationServiceImpl.java
@@ -16,6 +16,7 @@ import com.njcn.device.pq.service.INewStationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -24,7 +25,6 @@ import java.util.Map;
*
* 新能源场站高低电压穿越表 服务实现类
*
- *
* @author guofeihu
* @since 2024-08-14
*/
@@ -66,6 +66,7 @@ public class NewStationServiceImpl extends ServiceImpl listIds = Arrays.asList(ids.split(","));
//判断该新能源场站信息是否绑定了测点ID
diff --git a/pqs-event/event-api/pom.xml b/pqs-event/event-api/pom.xml
index 85b06eec7..7a9b3b1d7 100644
--- a/pqs-event/event-api/pom.xml
+++ b/pqs-event/event-api/pom.xml
@@ -56,6 +56,12 @@
jna
3.0.9
+
+ com.njcn
+ pms-device-api
+ 1.0.0
+ compile
+
diff --git a/pqs-event/event-api/src/main/java/com/njcn/event/api/TransientFeignClient.java b/pqs-event/event-api/src/main/java/com/njcn/event/api/TransientFeignClient.java
new file mode 100644
index 000000000..313ae8c2e
--- /dev/null
+++ b/pqs-event/event-api/src/main/java/com/njcn/event/api/TransientFeignClient.java
@@ -0,0 +1,22 @@
+package com.njcn.event.api;
+
+import com.njcn.common.pojo.constant.ServerInfo;
+import com.njcn.common.pojo.response.HttpResult;
+import com.njcn.device.pms.pojo.param.MonitorTerminalParam;
+import com.njcn.event.api.fallback.TransientFeignClientFallbackFactory;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+/**
+ * 暂态事件Feign客户端
+ * @author guofeihu
+ * @date 2024-08-22
+ */
+@FeignClient(value = ServerInfo.EVENT,path = "/transient",fallbackFactory = TransientFeignClientFallbackFactory.class)
+public interface TransientFeignClient {
+
+ @PostMapping("/getTransientAnalyseWaveToByteArray")
+ HttpResult getTransientAnalyseWaveToByteArray(@RequestBody MonitorTerminalParam param);
+
+}
diff --git a/pqs-event/event-api/src/main/java/com/njcn/event/api/fallback/TransientFeignClientFallbackFactory.java b/pqs-event/event-api/src/main/java/com/njcn/event/api/fallback/TransientFeignClientFallbackFactory.java
new file mode 100644
index 000000000..41e93454b
--- /dev/null
+++ b/pqs-event/event-api/src/main/java/com/njcn/event/api/fallback/TransientFeignClientFallbackFactory.java
@@ -0,0 +1,40 @@
+package com.njcn.event.api.fallback;
+
+import com.njcn.common.pojo.enums.response.CommonResponseEnum;
+import com.njcn.common.pojo.exception.BusinessException;
+import com.njcn.common.pojo.response.HttpResult;
+import com.njcn.device.pms.pojo.param.MonitorTerminalParam;
+import com.njcn.event.api.TransientFeignClient;
+import com.njcn.event.utils.EventlEnumUtil;
+import feign.hystrix.FallbackFactory;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.RequestBody;
+
+/**
+ * 暂态事件熔断降级
+ * @author guofeihu
+ * @date 2024-08-22
+ */
+@Slf4j
+@Component
+public class TransientFeignClientFallbackFactory implements FallbackFactory {
+
+ @Override
+ public TransientFeignClient create(Throwable throwable) {
+ //判断抛出异常是否为解码器抛出的业务异常
+ Enum> exceptionEnum = CommonResponseEnum.SERVICE_FALLBACK;
+ if (throwable.getCause() instanceof BusinessException) {
+ BusinessException businessException = (BusinessException) throwable.getCause();
+ exceptionEnum = EventlEnumUtil.getExceptionEnum(businessException.getResult());
+ }
+ Enum> finalExceptionEnum = exceptionEnum;
+ return new TransientFeignClient() {
+ @Override
+ public HttpResult getTransientAnalyseWaveToByteArray(@RequestBody MonitorTerminalParam param) {
+ log.error("{}异常,降级处理,异常为:{}", "暂态事件波形分析:", throwable.toString());
+ throw new BusinessException(finalExceptionEnum);
+ }
+ };
+ }
+}
diff --git a/pqs-event/event-boot/src/main/java/com/njcn/event/controller/majornetwork/TransientController.java b/pqs-event/event-boot/src/main/java/com/njcn/event/controller/majornetwork/TransientController.java
index 2b75a1946..238162eb3 100644
--- a/pqs-event/event-boot/src/main/java/com/njcn/event/controller/majornetwork/TransientController.java
+++ b/pqs-event/event-boot/src/main/java/com/njcn/event/controller/majornetwork/TransientController.java
@@ -23,6 +23,9 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
import java.util.List;
/**
@@ -60,6 +63,24 @@ public class TransientController extends BaseController {
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, wave, methodDescribe);
}
+ @OperateInfo(info = LogEnum.BUSINESS_COMMON)
+ @PostMapping("/getTransientAnalyseWaveToByteArray")
+ @ApiOperation("暂态事件波形分析(转byte数组)")
+ public HttpResult getTransientAnalyseWaveToByteArray(@RequestBody MonitorTerminalParam param){
+ byte[] bytes = null;
+ String methodDescribe = getMethodDescribe("getTransientAnalyseWaveToByteArray");
+ WaveDataDTO wave = transientService.getTransientAnalyseWave(param);
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(wave);
+ bytes = baos.toByteArray();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, bytes, methodDescribe);
+ }
+
@OperateInfo(info = LogEnum.BUSINESS_COMMON, operateType = OperateType.DOWNLOAD)
@PostMapping("/downloadWaveFile")
@ApiOperation("暂态波形下载")
diff --git a/pqs-prepare/prepare-api/src/main/java/com/njcn/prepare/harmonic/api/event/fallback/RActivePowerRangeFeignClientFallbackFactory.java b/pqs-prepare/prepare-api/src/main/java/com/njcn/prepare/harmonic/api/event/fallback/RActivePowerRangeFeignClientFallbackFactory.java
index 8b15f4270..1f0fee36c 100644
--- a/pqs-prepare/prepare-api/src/main/java/com/njcn/prepare/harmonic/api/event/fallback/RActivePowerRangeFeignClientFallbackFactory.java
+++ b/pqs-prepare/prepare-api/src/main/java/com/njcn/prepare/harmonic/api/event/fallback/RActivePowerRangeFeignClientFallbackFactory.java
@@ -34,13 +34,13 @@ public class RActivePowerRangeFeignClientFallbackFactory implements FallbackFact
return new RActivePowerRangeFeignClient() {
@Override
public HttpResult> record(RActivePowerRangeParam rActivePowerRangeParam) {
- log.error("{}异常,降级处理,异常为:{}", "有功功率趋势记录: ", throwable.toString());
+ log.error("{}异常,降级处理,异常为:{}", "有功功率趋势记录:", throwable.toString());
throw new BusinessException(finalExceptionEnum);
}
@Override
public HttpResult getDataByLineId(String lineId,String startTime,String endTime) {
- log.error("{}异常,降级处理,异常为:{}", "根据监测点ID获取有功功率趋势信息: ", throwable.toString());
+ log.error("{}异常,降级处理,异常为:{}", "根据监测点ID获取有功功率趋势信息:", throwable.toString());
throw new BusinessException(finalExceptionEnum);
}
};
diff --git a/pqs-prepare/prepare-api/src/main/java/com/njcn/prepare/harmonic/api/event/fallback/SpThroughFeignClientFallbackFactory.java b/pqs-prepare/prepare-api/src/main/java/com/njcn/prepare/harmonic/api/event/fallback/SpThroughFeignClientFallbackFactory.java
index c4b5bec83..beb13a3fa 100644
--- a/pqs-prepare/prepare-api/src/main/java/com/njcn/prepare/harmonic/api/event/fallback/SpThroughFeignClientFallbackFactory.java
+++ b/pqs-prepare/prepare-api/src/main/java/com/njcn/prepare/harmonic/api/event/fallback/SpThroughFeignClientFallbackFactory.java
@@ -33,19 +33,19 @@ public class SpThroughFeignClientFallbackFactory implements FallbackFactory record() {
- log.error("{}异常,降级处理,异常为:{}", "高低电压穿越记录: ", throwable.toString());
+ log.error("{}异常,降级处理,异常为:{}", "高低电压穿越记录:", throwable.toString());
throw new BusinessException(finalExceptionEnum);
}
@Override
public HttpResult getDataByEventIds(SpThroughParam spThroughParam) {
- log.error("{}异常,降级处理,异常为:{}", "根据事件ID集合及能源站类型获取高低电压穿越次数: ", throwable.toString());
+ log.error("{}异常,降级处理,异常为:{}", "根据事件ID集合及能源站类型获取高低电压穿越次数:", throwable.toString());
throw new BusinessException(finalExceptionEnum);
}
@Override
public HttpResult> formatEventIds(SpThroughParam spThroughParam) {
- log.error("{}异常,降级处理,异常为:{}", "根据原有的事件集合进行过滤: ", throwable.toString());
+ log.error("{}异常,降级处理,异常为:{}", "根据原有的事件集合进行过滤:", throwable.toString());
throw new BusinessException(finalExceptionEnum);
}
};
diff --git a/pqs-prepare/prepare-api/src/main/java/com/njcn/prepare/harmonic/pojo/po/SpThroughPO.java b/pqs-prepare/prepare-api/src/main/java/com/njcn/prepare/harmonic/pojo/po/SpThroughPO.java
index fc2a85ad8..a1ff5cb3a 100644
--- a/pqs-prepare/prepare-api/src/main/java/com/njcn/prepare/harmonic/pojo/po/SpThroughPO.java
+++ b/pqs-prepare/prepare-api/src/main/java/com/njcn/prepare/harmonic/pojo/po/SpThroughPO.java
@@ -3,6 +3,7 @@ package com.njcn.prepare.harmonic.pojo.po;
import com.baomidou.mybatisplus.annotation.TableName;
import com.njcn.db.bo.BaseEntity;
import lombok.Data;
+import java.time.LocalDateTime;
/**
* 高低电压穿越 实体类
@@ -45,4 +46,9 @@ public class SpThroughPO extends BaseEntity {
*/
private Boolean state;
+ /**
+ * 创建时间(自定义)
+ */
+ private LocalDateTime createTime;
+
}
diff --git a/pqs-prepare/prepare-boot/src/main/java/com/njcn/prepare/harmonic/service/mysql/Impl/event/RActivePowerRangeServiceImpl.java b/pqs-prepare/prepare-boot/src/main/java/com/njcn/prepare/harmonic/service/mysql/Impl/event/RActivePowerRangeServiceImpl.java
index bb965441b..1f17a07b3 100644
--- a/pqs-prepare/prepare-boot/src/main/java/com/njcn/prepare/harmonic/service/mysql/Impl/event/RActivePowerRangeServiceImpl.java
+++ b/pqs-prepare/prepare-boot/src/main/java/com/njcn/prepare/harmonic/service/mysql/Impl/event/RActivePowerRangeServiceImpl.java
@@ -23,6 +23,7 @@ import com.njcn.prepare.harmonic.service.mysql.event.RActivePowerRangeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
@@ -74,6 +75,7 @@ public class RActivePowerRangeServiceImpl extends MppServiceImpl record(RActivePowerRangeParam rActivePowerRangeParam) {
if(rActivePowerRangeParam == null){
rActivePowerRangeParam = new RActivePowerRangeParam();
@@ -404,13 +406,13 @@ public class RActivePowerRangeServiceImpl extends MppServiceImpl commonQuery(String tableName,String columnName,StatisticalDataDTO statisticalDataDTO,Integer start,Integer end){
List commonQueryParams = new ArrayList<>();
//不管哪种时间是固定的
String time = statisticalDataDTO.getTime().atZone(ZoneId.systemDefault()).format(formatter);
CommonQueryParam commonQueryParam = new CommonQueryParam();
- //无谐波次数查询
+ //无谐波次数指标查询
if(start == null){
commonQueryParam.setStartTime(time);
commonQueryParam.setEndTime(time);
@@ -421,7 +423,7 @@ public class RActivePowerRangeServiceImpl extends MppServiceImpl evenStDetailPOS = eventDetailFeignClient.getNewEventDetailByTime(getLastTime(),currentTime).getData();
+ MonitorTerminalParam monitorTerminalParam = new MonitorTerminalParam();
+ monitorTerminalParam.setSystemType(0);
+ monitorTerminalParam.setType(0);
for(RmpEventDetailPO rmpEventDetailPO : evenStDetailPOS){
//获取监测点
LineDTO lineDTO = commLineClient.getLineDetail(rmpEventDetailPO.getMeasurementPointId()).getData();
if(lineDTO != null && lineDTO.getNewStationId() != null){
+ //监测点必须绑定新能源场站
NewStation newStation = newStationClient.selectById(lineDTO.getNewStationId()).getData();
if(newStation != null){
- //waveFileComponent.getComtrade();
- //暂升事件
- if(Param.UPPEREVENT.equals(rmpEventDetailPO.getEventType())){
- //风电场
- if(Param.WINDFARM.equals(newStation.getStationType())){
-
- }
- //光伏电站
- if(Param.PHOTOVOLTAICPOWER.equals(newStation.getStationType())){
-
- }
- }
- //暂降事件
- if(Param.LOWEREVENT.equals(rmpEventDetailPO.getEventType())){
- //风电场
- if(Param.WINDFARM.equals(newStation.getStationType())){
-
- }
- //光伏电站
- if(Param.PHOTOVOLTAICPOWER.equals(newStation.getStationType())){
-
+ //事件不能重复统计(除非事件的暂降类型及变电站类型发生变化)
+ LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper();
+ lambdaQueryWrapper.eq(SpThroughPO::getEventId,rmpEventDetailPO.getEventId())
+ .eq(SpThroughPO::getEventType,rmpEventDetailPO.getEventType())
+ .eq(SpThroughPO::getStationType,newStation.getStationType())
+ .eq(SpThroughPO::getState,1);
+ if(this.baseMapper.selectList(lambdaQueryWrapper).isEmpty()){
+ //准备高低电压穿越实体bean
+ SpThroughPO spThroughPO = new SpThroughPO();
+ spThroughPO.setId(IdUtil.simpleUUID());
+ spThroughPO.setEventId(rmpEventDetailPO.getEventId());
+ spThroughPO.setEventType(rmpEventDetailPO.getEventType());
+ spThroughPO.setStationType(newStation.getStationType());
+ //默认该事件没有穿越
+ spThroughPO.setIsOrNot(0);
+ //设置波形查询的条件:事件ID
+ monitorTerminalParam.setId(rmpEventDetailPO.getEventId());
+ //获取RMS波形数据(由于WaveDataDTO为复杂对象所以转成byte数组在进行反序列化)
+ byte[] bytes = transientFeignClient.getTransientAnalyseWaveToByteArray(monitorTerminalParam).getData();
+ WaveDataDTO waveDataDTO = null;
+ try {
+ ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bis);
+ //强转成WaveDataDTO
+ waveDataDTO = (WaveDataDTO)ois.readObject();
+ } catch (Exception e) {
+ e.printStackTrace();
}
+ //标称电压
+ if(lineDTO.getVoltageLevel()!=null){
+ Float voltageLevel = Float.parseFloat(lineDTO.getVoltageLevel());
+ //格式化数据源
+ List> newListRmsData = listRmsDataFormat(waveDataDTO);
+ //暂升事件
+ if(Param.UPPEREVENT.equals(rmpEventDetailPO.getEventType())){
+ //风电场
+ if(Param.WINDFARM.equals(newStation.getStationType())){
+ if(isThrough(waveDataDTO,125,130,500,voltageLevel.floatValue(),newListRmsData)
+ && isThrough(waveDataDTO,120,125,1000,voltageLevel.floatValue(),newListRmsData)
+ && isThrough(waveDataDTO,110,120,10000,voltageLevel.floatValue(),newListRmsData)){
+ spThroughPO.setIsOrNot(1);
+ }
+ }
+ //光伏电站
+ if(Param.PHOTOVOLTAICPOWER.equals(newStation.getStationType())){
+ if(isThrough(waveDataDTO,125,130,500,voltageLevel.floatValue(),newListRmsData)
+ && isThrough(waveDataDTO,120,125,1000,voltageLevel.floatValue(),newListRmsData)
+ && isThrough(waveDataDTO,110,120,10000,voltageLevel.floatValue(),newListRmsData)){
+ spThroughPO.setIsOrNot(1);
+ }
+ }
+ }
+ //暂降事件
+ if(Param.LOWEREVENT.equals(rmpEventDetailPO.getEventType())){
+ //风电场
+ if(Param.WINDFARM.equals(newStation.getStationType())){
+ if(isThrough(waveDataDTO,20,-1,625,voltageLevel.floatValue(),newListRmsData)){
+ spThroughPO.setIsOrNot(1);
+ }
+ }
+ //光伏电站
+ if(Param.PHOTOVOLTAICPOWER.equals(newStation.getStationType())){
+ if(isThrough(waveDataDTO,0,-1,150,voltageLevel.floatValue(),newListRmsData)
+ && isThrough(waveDataDTO,20,-1,625,voltageLevel.floatValue(),newListRmsData)
+ && isThrough(waveDataDTO,20,90,-1,voltageLevel.floatValue(),newListRmsData)){
+ spThroughPO.setIsOrNot(1);
+ }
+ }
+ }
+ spThroughPO.setCreateTime(currentTime);
+ this.baseMapper.insert(spThroughPO);
+ };
}
}
}
}
+ }
+ private boolean isThrough(WaveDataDTO waveDataDTO,int start,int end,int ms,float voltageLevel,List> newListRmsData){
+ boolean isThrough = false;
+ //格式化RMS源数据
+ float startVoltageLevel = voltageLevel * (start / 100F);
+ float endVoltageLevel = -1;
+ if(end!=-1){
+ endVoltageLevel = voltageLevel * (end / 100F);
+ }
+ for (int i = 0; i < newListRmsData.size(); i++) {
+ for (int j = 1; j < newListRmsData.get(i).size(); j++) {
+ float curValue = newListRmsData.get(i).get(j);
+ //当电压达到目标值时
+ if(endVoltageLevel != -1 && startVoltageLevel < curValue && curValue <= endVoltageLevel){
+ isContinuity(newListRmsData,i+1,newListRmsData.get(i).get(0).intValue(),ms,j);
+ isThrough = true;
+ }else if(startVoltageLevel == curValue){
+ isContinuity(newListRmsData,i+1,newListRmsData.get(i).get(0).intValue(),ms,j);
+ isThrough = true;
+ }
+ }
+ }
+ return isThrough;
+ }
+
+ private boolean isContinuity(List> newListRmsData,int index,int curms,int ms,int p){
+ boolean isContinuity = false;
+ //记录电压有效毫秒数
+ Set effectiveMs = new HashSet<>();
+ for (int k = curms + 1 ; k <= curms + ms; k++) {
+ effectiveMs.add(k);
+ }
+ int count = 0;
+ for (int i = index; i < newListRmsData.size(); i++) {
+ for (int j = 0; j < newListRmsData.get(i).size(); j++) {
+ int curVallue = newListRmsData.get(i).get(0).intValue();
+ //如果当前相别的电压毫秒数在有效期范围内则记录下数字
+ if(effectiveMs.contains(curVallue) && checkListIsNull(newListRmsData.get(i),p)!=null){
+ count ++;
+ }
+ }
+ }
+ if(count >= effectiveMs.size()){
+ isContinuity = true;
+ }
+ return isContinuity;
+ }
+
+ private Float checkListIsNull(List list ,int index){
+ try {
+ return list.get(index);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ //格式化RMS数据:将listRmsData中的电压数据取出在根据pt变比组成新的RMS数据
+ private List> listRmsDataFormat(WaveDataDTO waveDataDTO){
+ List> newListRmsData = new ArrayList<>();
+ List indexs = new ArrayList<>();
+ //根据channelNames取出电压对应listRmsData数据中的数据索引
+ for (int i = 0; i < waveDataDTO.getChannelNames().size(); i++) {
+ if(waveDataDTO.getChannelNames().get(i).indexOf("电压")!=-1){
+ indexs.add(i);
+ }
+ }
+ //前端展示的波形图数据来源就是这个所以这边也跟前端保持一致
+ for (int i = 0; i < waveDataDTO.getListRmsData().size(); i++) {
+ List cur = waveDataDTO.getListRmsData().get(i);
+ List newCur = new ArrayList<>();
+ //数组第一个为时间
+ newCur.add(cur.get(0));
+ //便利电压数据的索引
+ for(Integer index : indexs){
+ //根据PT变比算出新的数据(前端取的一次值,也是根据pt变比算出的,所以这边和前端保持一致)新增到新的数组中
+ newCur.add(cur.get(index) * Float.parseFloat((waveDataDTO.getPt() / 1000F)+""));
+ }
+ newListRmsData.add(newCur);
+ }
+ return newListRmsData;
}
//拿到最近一次插入高低电压穿越表信息的时间