Jelajahi Sumber

解析后台功能初版(未测试)

tl 7 bulan lalu
induk
melakukan
326a5acf2c
49 mengubah file dengan 2678 tambahan dan 610 penghapusan
  1. 54 0
      cpp-admin/src/main/java/com/cpp/web/domain/AbnormalAlarm.java
  2. 15 6
      cpp-admin/src/main/java/com/cpp/web/domain/BaseCppEntity.java
  3. 145 37
      cpp-admin/src/main/java/com/cpp/web/domain/cloud/NwpCloud.java
  4. 0 6
      cpp-admin/src/main/java/com/cpp/web/domain/datafactory/BaseParsing.java
  5. 16 4
      cpp-admin/src/main/java/com/cpp/web/domain/datafactory/ParsingCdq.java
  6. 13 0
      cpp-admin/src/main/java/com/cpp/web/domain/datafactory/ParsingDq.java
  7. 4 11
      cpp-admin/src/main/java/com/cpp/web/domain/datafactory/ParsingFileUrl.java
  8. 13 8
      cpp-admin/src/main/java/com/cpp/web/domain/datafactory/ParsingLog.java
  9. 16 0
      cpp-admin/src/main/java/com/cpp/web/domain/datafactory/ParsingRp.java
  10. 0 4
      cpp-admin/src/main/java/com/cpp/web/domain/datafactory/ParsingType.java
  11. 3 1
      cpp-admin/src/main/java/com/cpp/web/domain/datafactory/enums/FileTypeEnum.java
  12. 23 0
      cpp-admin/src/main/java/com/cpp/web/domain/enums/AlarmEnum.java
  13. 5 4
      cpp-admin/src/main/java/com/cpp/web/domain/enums/DataSourcesEnum.java
  14. 0 7
      cpp-admin/src/main/java/com/cpp/web/domain/station/ElectricField.java
  15. 64 0
      cpp-admin/src/main/java/com/cpp/web/domain/station/ForecastPowerShortTermRegulation.java
  16. 16 0
      cpp-admin/src/main/java/com/cpp/web/domain/station/ForecastPowerShortTermStation.java
  17. 60 0
      cpp-admin/src/main/java/com/cpp/web/domain/station/ForecastPowerUltraShortTermRegulation.java
  18. 16 4
      cpp-admin/src/main/java/com/cpp/web/domain/station/ForecastPowerUltraShortTermStation.java
  19. 0 79
      cpp-admin/src/main/java/com/cpp/web/domain/station/InverterStatusData.java
  20. 6 80
      cpp-admin/src/main/java/com/cpp/web/domain/station/PowerStationStatusData.java
  21. 0 81
      cpp-admin/src/main/java/com/cpp/web/domain/station/WeatherStationStatusData.java
  22. 0 80
      cpp-admin/src/main/java/com/cpp/web/domain/station/WindTowerStatusData.java
  23. 0 70
      cpp-admin/src/main/java/com/cpp/web/domain/station/WindTurbineStatusData.java
  24. 17 0
      cpp-admin/src/main/java/com/cpp/web/mapper/AbnormalAlarmMapper.java
  25. 15 0
      cpp-admin/src/main/java/com/cpp/web/mapper/station/ForecastPowerShortTermRegulationMapper.java
  26. 15 0
      cpp-admin/src/main/java/com/cpp/web/mapper/station/ForecastPowerUltraShortTermRegulationMapper.java
  27. 15 0
      cpp-admin/src/main/java/com/cpp/web/service/AbnormalAlarmService.java
  28. 572 0
      cpp-admin/src/main/java/com/cpp/web/service/cloud/CloudFileParsing.java
  29. 1 2
      cpp-admin/src/main/java/com/cpp/web/service/cloud/ForecastPowerShortTermCloudService.java
  30. 87 60
      cpp-admin/src/main/java/com/cpp/web/service/datafactory/FtpFileParsing.java
  31. 14 22
      cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingCdqServiceImpl.java
  32. 3 3
      cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingCftServiceImpl.java
  33. 47 14
      cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingDqServiceImpl.java
  34. 2 2
      cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingFjServiceImpl.java
  35. 2 2
      cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingNbqServiceImpl.java
  36. 2 2
      cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingNwpServiceImpl.java
  37. 2 2
      cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingQxzServiceImpl.java
  38. 217 0
      cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingRcdqServiceImpl.java
  39. 242 0
      cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingRdqServiceImpl.java
  40. 14 19
      cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingRpServiceImpl.java
  41. 136 0
      cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingStatusServiceImpl.java
  42. 21 0
      cpp-admin/src/main/java/com/cpp/web/service/impl/AbnormalAlarmServiceImpl.java
  43. 37 0
      cpp-admin/src/main/java/com/cpp/web/service/station/ForecastPowerShortTermRegulationService.java
  44. 20 0
      cpp-admin/src/main/java/com/cpp/web/service/station/ForecastPowerUltraShortTermRegulationService.java
  45. 49 0
      cpp-admin/src/main/java/com/cpp/web/service/station/impl/ForecastPowerShortTermRegulationServiceImpl.java
  46. 51 0
      cpp-admin/src/main/java/com/cpp/web/service/station/impl/ForecastPowerUltraShortTermRegulationServiceImpl.java
  47. 441 0
      cpp-admin/src/main/java/com/cpp/web/utils/DateTimeUtil.java
  48. 46 0
      cpp-admin/src/main/java/com/cpp/web/utils/MessageUtils.java
  49. 141 0
      cpp-admin/src/main/java/com/cpp/web/utils/NumberUtils.java

+ 54 - 0
cpp-admin/src/main/java/com/cpp/web/domain/AbnormalAlarm.java

@@ -0,0 +1,54 @@
+package com.cpp.web.domain;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.cpp.web.domain.enums.AlarmEnum;
+import com.cpp.web.domain.enums.DataSourcesEnum;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 异常告警实体(包括站端云端中心侧的关键信息)
+ *
+ * @author tl
+ * @date 2024-09-23 15:28:33
+ */
+@Data
+@TableName("cpp_abnormal_alarm")
+@EqualsAndHashCode(callSuper = true)
+@ApiModel(value = "cpp_abnormal_alarm")
+public class AbnormalAlarm extends BaseCppEntity {
+
+    /**
+     * 告警来源
+     */
+    private DataSourcesEnum alarmSource;
+
+
+    /**
+     * 告警类型
+     */
+    private AlarmEnum alarmType;
+
+
+    /**
+     * 告警详情
+     */
+    private String msg;
+
+    /**
+     * 告警状态 1:已确认 0:未确认
+     */
+    private Integer status = 0;
+
+
+    public AbnormalAlarm(DataSourcesEnum alarmSource, AlarmEnum alarmType, String msg, String stationCode) {
+        this.alarmSource = alarmSource;
+        this.alarmType = alarmType;
+        this.msg = msg;
+        super.setStationCode(stationCode);
+    }
+
+    public AbnormalAlarm() {
+    }
+}

+ 15 - 6
cpp-admin/src/main/java/com/cpp/web/domain/BaseCppEntity.java

@@ -9,8 +9,13 @@ import lombok.Data;
 
 import java.io.Serializable;
 import java.time.LocalDateTime;
-import java.util.HashMap;
-import java.util.Map;
+
+/**
+ * cpp_electric_field
+ *
+ * @author tl
+ * @date 2024-09-23 15:28:33
+ */
 @Data
 public class BaseCppEntity implements Serializable {
     private static final long serialVersionUID = 1L;
@@ -19,6 +24,13 @@ public class BaseCppEntity implements Serializable {
     @ApiModelProperty(value = "主键ID")
     private Long id;
 
+
+    /**
+     * 场站编号
+     */
+    @ApiModelProperty(value = "场站编号")
+    private String stationCode;
+
     /**
      * 创建者
      */
@@ -44,8 +56,5 @@ public class BaseCppEntity implements Serializable {
     private LocalDateTime lastModifyTime;
 
 
-    /**
-     * 场站标识
-     */
-    private String stationCode;
+
 }

+ 145 - 37
cpp-admin/src/main/java/com/cpp/web/domain/cloud/NwpCloud.java

@@ -116,6 +116,13 @@ public class NwpCloud extends BaseCppEntity {
     @Digits(integer = 10, fraction = 2)
     private BigDecimal ws10 = new BigDecimal(-99);
 
+    /**
+     * 20米风速
+     */
+    @ApiModelProperty(value = "20米风速")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal ws20 = new BigDecimal(-99);
+
 
     /**
      * 30米风速
@@ -124,6 +131,14 @@ public class NwpCloud extends BaseCppEntity {
     @Digits(integer = 10, fraction = 2)
     private BigDecimal ws30 = new BigDecimal(-99);
 
+    /**
+     * 40米风速
+     */
+    @ApiModelProperty(value = "40米风速")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal ws40 = new BigDecimal(-99);
+
+
 
     /**
      * 50米风速
@@ -132,6 +147,13 @@ public class NwpCloud extends BaseCppEntity {
     @Digits(integer = 10, fraction = 2)
     private BigDecimal ws50 = new BigDecimal(-99);
 
+    /**
+     * 60米风速
+     */
+    @ApiModelProperty(value = "60米风速")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal ws60 = new BigDecimal(-99);
+
 
     /**
      * 70米风速
@@ -164,6 +186,49 @@ public class NwpCloud extends BaseCppEntity {
     @Digits(integer = 10, fraction = 2)
     private BigDecimal ws100 = new BigDecimal(-99);
 
+    /**
+     * 110米风速
+     */
+    @ApiModelProperty(value = "110米风速")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal ws110 = new BigDecimal(-99);
+
+    /**
+     * 120米风速
+     */
+    @ApiModelProperty(value = "120米风速")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal ws120 = new BigDecimal(-99);
+
+    /**
+     * 130米风速
+     */
+    @ApiModelProperty(value = "130米风速")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal ws130 = new BigDecimal(-99);
+
+    /**
+     * 140米风速
+     */
+    @ApiModelProperty(value = "140米风速")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal ws140 = new BigDecimal(-99);
+
+    /**
+     * 150米风速
+     */
+    @ApiModelProperty(value = "150米风速")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal ws150 = new BigDecimal(-99);
+
+    /**
+     * 160米风速
+     */
+    @ApiModelProperty(value = "160米风速")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal ws160 = new BigDecimal(-99);
+
+
 
     /**
      * 170米风速
@@ -172,6 +237,28 @@ public class NwpCloud extends BaseCppEntity {
     @Digits(integer = 10, fraction = 2)
     private BigDecimal ws170 = new BigDecimal(-99);
 
+    /**
+     * 180米风速
+     */
+    @ApiModelProperty(value = "180米风速")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal ws180 = new BigDecimal(-99);
+
+    /**
+     * 190米风速
+     */
+    @ApiModelProperty(value = "190米风速")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal ws190 = new BigDecimal(-99);
+
+    /**
+     * 200米风速
+     */
+    @ApiModelProperty(value = "200米风速")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal ws200 = new BigDecimal(-99);
+
+
 
     /**
      * 10米风向
@@ -180,6 +267,13 @@ public class NwpCloud extends BaseCppEntity {
     @Digits(integer = 10, fraction = 2)
     private BigDecimal wd10 = new BigDecimal(-99);
 
+    /**
+     * 20米风向
+     */
+    @ApiModelProperty(value = "20米风向")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal wd20 = new BigDecimal(-99);
+
 
     /**
      * 30米风向
@@ -188,6 +282,12 @@ public class NwpCloud extends BaseCppEntity {
     @Digits(integer = 10, fraction = 2)
     private BigDecimal wd30 = new BigDecimal(-99);
 
+    /**
+     * 40米风向
+     */
+    @ApiModelProperty(value = "40米风向")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal wd40 = new BigDecimal(-99);
 
     /**
      * 50米风向
@@ -196,6 +296,12 @@ public class NwpCloud extends BaseCppEntity {
     @Digits(integer = 10, fraction = 2)
     private BigDecimal wd50 = new BigDecimal(-99);
 
+    /**
+     * 60米风向
+     */
+    @ApiModelProperty(value = "60米风向")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal wd60 = new BigDecimal(-99);
 
     /**
      * 70米风向
@@ -228,74 +334,76 @@ public class NwpCloud extends BaseCppEntity {
     @Digits(integer = 10, fraction = 2)
     private BigDecimal wd100 = new BigDecimal(-99);
 
-
     /**
-     * 170米风向
+     * 110米风向
      */
-    @ApiModelProperty(value = "170米风向")
+    @ApiModelProperty(value = "110米风向")
     @Digits(integer = 10, fraction = 2)
-    private BigDecimal wd170 = new BigDecimal(-99);
+    private BigDecimal wd110 = new BigDecimal(-99);
 
     /**
-     * 110米风速
-     */
-    @ApiModelProperty(value = "110米风速")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal ws110 = new BigDecimal(-99);
-    /**
-     * 120米风速
+     * 120米风向
      */
-    @ApiModelProperty(value = "120米风")
+    @ApiModelProperty(value = "120米风向")
     @Digits(integer = 10, fraction = 2)
-    private BigDecimal ws120 = new BigDecimal(-99);
+    private BigDecimal wd120 = new BigDecimal(-99);
+
     /**
-     * 130米风
+     * 130米风
      */
-    @ApiModelProperty(value = "130米风")
+    @ApiModelProperty(value = "130米风")
     @Digits(integer = 10, fraction = 2)
-    private BigDecimal ws130 = new BigDecimal(-99);
+    private BigDecimal wd130 = new BigDecimal(-99);
+
     /**
-     * 140米风
+     * 140米风
      */
-    @ApiModelProperty(value = "140米风")
+    @ApiModelProperty(value = "140米风")
     @Digits(integer = 10, fraction = 2)
-    private BigDecimal ws140 = new BigDecimal(-99);
+    private BigDecimal wd140 = new BigDecimal(-99);
+
     /**
-     * 150米风
+     * 150米风
      */
-    @ApiModelProperty(value = "150米风")
+    @ApiModelProperty(value = "150米风")
     @Digits(integer = 10, fraction = 2)
-    private BigDecimal ws150 = new BigDecimal(-99);
+    private BigDecimal wd150 = new BigDecimal(-99);
+
     /**
-     * 110米风向
+     * 160米风向
      */
-    @ApiModelProperty(value = "110米风向")
+    @ApiModelProperty(value = "160米风向")
     @Digits(integer = 10, fraction = 2)
-    private BigDecimal wd110 = new BigDecimal(-99);
+    private BigDecimal wd160 = new BigDecimal(-99);
+
     /**
-     * 120米风向
+     * 170米风向
      */
-    @ApiModelProperty(value = "120米风向")
+    @ApiModelProperty(value = "170米风向")
     @Digits(integer = 10, fraction = 2)
-    private BigDecimal wd120 = new BigDecimal(-99);
+    private BigDecimal wd170 = new BigDecimal(-99);
+
     /**
-     * 130米风向
+     * 180米风向
      */
-    @ApiModelProperty(value = "130米风向")
+    @ApiModelProperty(value = "180米风向")
     @Digits(integer = 10, fraction = 2)
-    private BigDecimal wd130 = new BigDecimal(-99);
+    private BigDecimal wd180 = new BigDecimal(-99);
+
     /**
-     * 140米风向
+     * 190米风向
      */
-    @ApiModelProperty(value = "140米风向")
+    @ApiModelProperty(value = "190米风向")
     @Digits(integer = 10, fraction = 2)
-    private BigDecimal wd140 = new BigDecimal(-99);
+    private BigDecimal wd190 = new BigDecimal(-99);
+
     /**
-     * 150米风向
+     * 200米风向
      */
-    @ApiModelProperty(value = "150米风向")
+    @ApiModelProperty(value = "200米风向")
     @Digits(integer = 10, fraction = 2)
-    private BigDecimal wd150 = new BigDecimal(-99);
+    private BigDecimal wd200 = new BigDecimal(-99);
+
     /**
      * 降水总量
      */

+ 0 - 6
cpp-admin/src/main/java/com/cpp/web/domain/datafactory/BaseParsing.java

@@ -36,10 +36,4 @@ public class BaseParsing extends BaseCppEntity {
     @ApiModelProperty(value = "文件类型")
     private String fileType;
 
-
-    /**
-     * 场站编码
-     */
-    @ApiModelProperty(value = "场站编码")
-    private String stationCode;
 }

+ 16 - 4
cpp-admin/src/main/java/com/cpp/web/domain/datafactory/ParsingCdq.java

@@ -7,7 +7,9 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
+import javax.validation.constraints.Digits;
 import java.io.Serializable;
+import java.math.BigDecimal;
 
 /**
  * cdq解析配置
@@ -20,10 +22,7 @@ import java.io.Serializable;
 @EqualsAndHashCode(callSuper = true)
 @ApiModel(value = "cpp_parsing_cdq")
 public class ParsingCdq extends BaseParsing {
-
-
-
-
+    
 
     /**
      * 数据生成日期
@@ -44,6 +43,19 @@ public class ParsingCdq extends BaseParsing {
      */
     @ApiModelProperty(value = "预测数据")
     private String fpValue;
+    
+    /**
+     * 开机容量
+     */
+    @ApiModelProperty(value = "开机容量")
+    private String openCapacity;
+
+
+//    /**
+//     * 装机容量
+//     */
+//    @ApiModelProperty(value = "装机容量")
+//    private String capacity;
 
 
 }

+ 13 - 0
cpp-admin/src/main/java/com/cpp/web/domain/datafactory/ParsingDq.java

@@ -43,5 +43,18 @@ public class ParsingDq extends BaseParsing{
 
 
 
+    /**
+     * 开机容量
+     */
+    @ApiModelProperty(value = "开机容量")
+    private String openCapacity;
+
+
+    /**
+     * 装机容量
+     */
+    @ApiModelProperty(value = "装机容量")
+    private String capacity;
+
 
 }

+ 4 - 11
cpp-admin/src/main/java/com/cpp/web/domain/datafactory/ParsingFileUrl.java

@@ -3,10 +3,10 @@ package com.cpp.web.domain.datafactory;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
-import com.cpp.common.annotation.Excel;
 import com.cpp.common.core.domain.BaseEntity;
+import com.cpp.web.domain.BaseCppEntity;
 import com.cpp.web.domain.datafactory.enums.FileTypeEnum;
-import com.cpp.web.domain.datafactory.enums.ParsingDataSourcesEnum;
+import com.cpp.web.domain.enums.DataSourcesEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -23,7 +23,7 @@ import lombok.EqualsAndHashCode;
 @EqualsAndHashCode(callSuper = true)
 @ApiModel(value = "cpp_parsing_file_url")
 @Data
-public class ParsingFileUrl extends BaseEntity {
+public class ParsingFileUrl extends BaseCppEntity {
 
     /**
      * Id
@@ -34,17 +34,10 @@ public class ParsingFileUrl extends BaseEntity {
 
 
     /**
-     * 场站编号
-     */
-    @ApiModelProperty(value = "场站编号")
-    private String stationCode;
-
-
-    /**
      * 解析分类(云端预测,站端上报)
      */
     @ApiModelProperty(value = "解析分类")
-    private ParsingDataSourcesEnum parsingDataSources;
+    private DataSourcesEnum parsingDataSources;
 
     /**
      * 文件类型

+ 13 - 8
cpp-admin/src/main/java/com/cpp/web/domain/datafactory/ParsingLog.java

@@ -1,15 +1,14 @@
 package com.cpp.web.domain.datafactory;
 
 import com.baomidou.mybatisplus.annotation.TableName;
-import com.cpp.common.annotation.Excel;
-import com.cpp.common.core.domain.BaseEntity;
 import com.cpp.web.domain.BaseCppEntity;
 import com.cpp.web.domain.datafactory.enums.FileTypeEnum;
+import com.cpp.web.domain.enums.DataSourcesEnum;
 import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
-import java.io.Serializable;
 import java.util.Date;
 
 /**
@@ -24,30 +23,36 @@ public class ParsingLog extends BaseCppEntity {
     /**
      * 文件名
      */
-    @Excel(name = "文件名")
+    @ApiModelProperty(value = "文件名")
     private String fileName;
 
     /**
      * 文件解析状态
      */
-    @Excel(name = "文件解析状态:成功/失败")
+    @ApiModelProperty(value = "文件解析状态:成功/失败")
     private String parsingFileStatus;
 
     /**
+     * 解析数据来源
+     */
+    @ApiModelProperty(value = "解析数据来源")
+    private DataSourcesEnum dataSources;
+    
+    /**
      * 文件解析状态描述
      */
-    @Excel(name = "文件解析状态描述")
+    @ApiModelProperty(value = "文件解析状态描述")
     private String parsingDescribe;
 
     /**
      * 解析时间
      */
-    @Excel(name = "解析时间")
+    @ApiModelProperty(value = "解析时间")
     private Date parsingTime;
 
     /**
      * 文件类型
      */
-    @Excel(name = "文件类型")
+    @ApiModelProperty(value = "文件类型")
     private FileTypeEnum fileType;
 }

+ 16 - 0
cpp-admin/src/main/java/com/cpp/web/domain/datafactory/ParsingRp.java

@@ -6,7 +6,9 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
+import javax.validation.constraints.Digits;
 import java.io.Serializable;
+import java.math.BigDecimal;
 
 /**
  * rp解析配置
@@ -60,4 +62,18 @@ public class ParsingRp extends BaseParsing {
      */
     @ApiModelProperty(value = "装机容量(MW)")
     private String capacity;
+
+    /**
+     * 站内受阻容量(故障/检修)(MW)
+     */
+    @ApiModelProperty(value = "受阻容量(故障/检修)(MW)")
+    private String blockedCapacity;
+
+
+    /**
+     * 限电标记
+     */
+    @ApiModelProperty(value = "限电标记 0不限电 1限电(MW)")
+    private String powerRationing;
+
 }

+ 0 - 4
cpp-admin/src/main/java/com/cpp/web/domain/datafactory/ParsingType.java

@@ -1,10 +1,6 @@
 package com.cpp.web.domain.datafactory;
 
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
-import com.cpp.common.annotation.Excel;
-import com.cpp.common.core.domain.BaseEntity;
 import com.cpp.web.domain.BaseCppEntity;
 import com.cpp.web.domain.datafactory.enums.FileTypeEnum;
 import io.swagger.annotations.ApiModel;

+ 3 - 1
cpp-admin/src/main/java/com/cpp/web/domain/datafactory/enums/FileTypeEnum.java

@@ -14,7 +14,9 @@ public enum FileTypeEnum {
     qxz(6, "气象站"),
     cft(7, "测风塔"),
     nbq(8, "逆变器"),
-    fj(9, "风机");
+    fj(9, "风机"),
+    rdq(10, "调控后短期"),
+    rcdq(11, "调控后超短期");
 
     private Integer code;
     private String message;

+ 23 - 0
cpp-admin/src/main/java/com/cpp/web/domain/enums/AlarmEnum.java

@@ -0,0 +1,23 @@
+package com.cpp.web.domain.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 解析通道类型
+ *
+ * @Author: tl
+ * @Date: 2023/6/2 14:24
+ */
+@Getter
+@AllArgsConstructor
+public enum AlarmEnum {
+
+    E1(1, "站端通道告警"),
+    E2(2, "站端上报告警"),
+    E3(2, "站端硬件报警"),
+    E4(4, "中心解析告警"),
+    E5(5, "通用告警"),;
+    private Integer code;
+    private String message;
+}

+ 5 - 4
cpp-admin/src/main/java/com/cpp/web/domain/datafactory/enums/ParsingDataSourcesEnum.java → cpp-admin/src/main/java/com/cpp/web/domain/enums/DataSourcesEnum.java

@@ -1,4 +1,4 @@
-package com.cpp.web.domain.datafactory.enums;
+package com.cpp.web.domain.enums;
 
 import lombok.AllArgsConstructor;
 import lombok.Getter;
@@ -11,10 +11,11 @@ import lombok.Getter;
  */
 @Getter
 @AllArgsConstructor
-public enum ParsingDataSourcesEnum {
+public enum DataSourcesEnum {
 
-    E1(1, "ftp(站端)"),
-    E2(2, "云端(中心侧)");
+    E1(1, "ftp(场站端)"),
+    E2(2, "云端(中心端)"),
+    E3(2, "集中预测(控制端)");
     private Integer code;
     private String message;
 }

+ 0 - 7
cpp-admin/src/main/java/com/cpp/web/domain/station/ElectricField.java

@@ -2,7 +2,6 @@ package com.cpp.web.domain.station;
 
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.cpp.web.domain.BaseCppEntity;
-import com.cpp.web.domain.station.enums.ProvinceEnum;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -21,12 +20,6 @@ import java.math.BigDecimal;
 public class ElectricField extends BaseCppEntity {
 
 
-    /**
-     * 场站编号
-     */
-    @ApiModelProperty(value = "场站编号")
-    private String stationCode;
-
 
     /**
      * 电站名称

+ 64 - 0
cpp-admin/src/main/java/com/cpp/web/domain/station/ForecastPowerShortTermRegulation.java

@@ -0,0 +1,64 @@
+package com.cpp.web.domain.station;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.cpp.web.domain.BaseCppEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import javax.validation.constraints.Digits;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 站端调控后预测短期
+ *
+ * @author tl
+ * @date 2024-09-23 15:28:33
+ */
+@Data
+@TableName("cpp_forecast_power_short_term_regulation")
+@EqualsAndHashCode(callSuper = true)
+@ApiModel(value = "cpp_forecast_power_short_term_regulation")
+public class ForecastPowerShortTermRegulation extends BaseCppEntity {
+
+
+    /**
+     * 预测时间
+     */
+    @ApiModelProperty(value = "预测值时间")
+    private Date time;
+
+
+    /**
+     * 预测功率
+     */
+    @ApiModelProperty(value = "预测功率")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal fpValue = new BigDecimal(-99);
+
+    /**
+     * 开机容量
+     */
+    @ApiModelProperty(value = "开机容量")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal openCapacity = new BigDecimal(-99);
+
+
+    /**
+     * 装机容量
+     */
+    @ApiModelProperty(value = "装机容量")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal capacity = new BigDecimal(-99);
+
+
+    /**
+     * 提前多久预测
+     */
+    @ApiModelProperty(value = "提前多久预测")
+    private Integer forecastHowLongAgo;
+
+
+}

+ 16 - 0
cpp-admin/src/main/java/com/cpp/web/domain/station/ForecastPowerShortTermStation.java

@@ -39,6 +39,22 @@ public class ForecastPowerShortTermStation extends BaseCppEntity {
     private BigDecimal fpValue = new BigDecimal(-99);
 
     /**
+     * 开机容量
+     */
+    @ApiModelProperty(value = "开机容量")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal openCapacity = new BigDecimal(-99);
+
+
+    /**
+     * 装机容量
+     */
+    @ApiModelProperty(value = "装机容量")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal capacity = new BigDecimal(-99);
+
+
+    /**
      * 提前多久预测
      */
     @ApiModelProperty(value = "提前多久预测")

+ 60 - 0
cpp-admin/src/main/java/com/cpp/web/domain/station/ForecastPowerUltraShortTermRegulation.java

@@ -0,0 +1,60 @@
+package com.cpp.web.domain.station;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.cpp.web.domain.BaseCppEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import javax.validation.constraints.Digits;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 站端调控后预测超短期
+ *
+ * @author tl
+ * @date 2024-09-23 15:28:33
+ */
+@Data
+@TableName("cpp_forecast_power_ultra_short_term_regulation")
+@EqualsAndHashCode(callSuper = true)
+@ApiModel(value = "cpp_forecast_power_ultra_short_term_regulation")
+public class ForecastPowerUltraShortTermRegulation extends BaseCppEntity {
+
+    /**
+     * 预测时间
+     */
+    @ApiModelProperty(value = "预测值时间")
+    private Date time;
+
+    /**
+     * 预测功率
+     */
+    @ApiModelProperty(value = "预测功率")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal fpValue = new BigDecimal(-99);
+
+    /**
+     * 开机容量
+     */
+    @ApiModelProperty(value = "开机容量")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal openCapacity = new BigDecimal(-99);
+
+//
+//    /**
+//     * 装机容量
+//     */
+//    @ApiModelProperty(value = "装机容量")
+//    @Digits(integer = 10, fraction = 2)
+//    private BigDecimal capacity = new BigDecimal(-99);
+//
+
+    /**
+     * 提前多久预测
+     */
+    @ApiModelProperty(value = "提前多久预测")
+    private Integer forecastHowLongAgo;
+}

+ 16 - 4
cpp-admin/src/main/java/com/cpp/web/domain/station/ForecastPowerUltraShortTermStation.java

@@ -23,14 +23,12 @@ import java.util.Date;
 @ApiModel(value = "cpp_forecast_power_ultra_short_term_station")
 public class ForecastPowerUltraShortTermStation extends BaseCppEntity {
 
-
     /**
      * 预测时间
      */
     @ApiModelProperty(value = "预测值时间")
     private Date time;
 
-
     /**
      * 预测功率
      */
@@ -38,11 +36,25 @@ public class ForecastPowerUltraShortTermStation extends BaseCppEntity {
     @Digits(integer = 10, fraction = 2)
     private BigDecimal fpValue = new BigDecimal(-99);
 
+
+    /**
+     * 开机容量
+     */
+    @ApiModelProperty(value = "开机容量")
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal openCapacity = new BigDecimal(-99);
+
+//
+//    /**
+//     * 装机容量
+//     */
+//    @ApiModelProperty(value = "装机容量")
+//    @Digits(integer = 10, fraction = 2)
+//    private BigDecimal capacity = new BigDecimal(-99);
+
     /**
      * 提前多久预测
      */
     @ApiModelProperty(value = "提前多久预测")
     private Integer forecastHowLongAgo;
-
-
 }

+ 0 - 79
cpp-admin/src/main/java/com/cpp/web/domain/station/InverterStatusData.java

@@ -47,85 +47,6 @@ public class InverterStatusData extends BaseCppEntity {
     private Date time;
 
 
-    /**
-     * 备用字段1
-     */
-    @ApiModelProperty(value = "备用字段1")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data1 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段2
-     */
-    @ApiModelProperty(value = "备用字段2")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data2 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段3
-     */
-    @ApiModelProperty(value = "备用字段3")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data3 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段4
-     */
-    @ApiModelProperty(value = "备用字段4")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data4 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段5
-     */
-    @ApiModelProperty(value = "备用字段5")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data5 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段6
-     */
-    @ApiModelProperty(value = "备用字段6")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data6 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段7
-     */
-    @ApiModelProperty(value = "备用字段7")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data7 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段8
-     */
-    @ApiModelProperty(value = "备用字段8")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data8 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段9
-     */
-    @ApiModelProperty(value = "备用字段9")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data9 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段10
-     */
-    @ApiModelProperty(value = "备用字段10")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data10 = new BigDecimal(-99);
-
 
     /**
      * 有功(KW)

+ 6 - 80
cpp-admin/src/main/java/com/cpp/web/domain/station/PowerStationStatusData.java

@@ -32,22 +32,6 @@ public class PowerStationStatusData extends BaseCppEntity {
     @ApiModelProperty(value = "时间")
     private Date time;
 
-
-    /**
-     * 备用字段9
-     */
-    @ApiModelProperty(value = "备用字段9")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data9 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段10
-     */
-    @ApiModelProperty(value = "备用字段10")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data10 = new BigDecimal(-99);
-
     /**
      * 实际功率(MW)
      */
@@ -86,77 +70,19 @@ public class PowerStationStatusData extends BaseCppEntity {
     @Digits(integer = 10, fraction = 2)
     private BigDecimal capacity = new BigDecimal(-99);
 
-
-
     /**
-     * jsonText
+     * 站内受阻容量(故障/检修)(MW)
      */
-    @ApiModelProperty(value = "jsonText")
-    private String jsonText;
-
-
-
-    /**
-     * 备用字段1
-     */
-    @ApiModelProperty(value = "备用字段1")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data1 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段2
-     */
-    @ApiModelProperty(value = "备用字段2")
+    @ApiModelProperty(value = "受阻容量(故障/检修)(MW)")
     @Digits(integer = 10, fraction = 2)
-    private BigDecimal data2 = new BigDecimal(-99);
+    private BigDecimal blockedCapacity = new BigDecimal(-99);
 
 
     /**
-     * 备用字段3
+     * 限电标记
      */
-    @ApiModelProperty(value = "备用字段3")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data3 = new BigDecimal(-99);
-
+    @ApiModelProperty(value = "限电标记 0不限电 1限电(MW)")
+    private Integer powerRationing = 0;
 
-    /**
-     * 备用字段4
-     */
-    @ApiModelProperty(value = "备用字段4")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data4 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段5
-     */
-    @ApiModelProperty(value = "备用字段5")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data5 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段6
-     */
-    @ApiModelProperty(value = "备用字段6")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data6 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段7
-     */
-    @ApiModelProperty(value = "备用字段7")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data7 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段8
-     */
-    @ApiModelProperty(value = "备用字段8")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data8 = new BigDecimal(-99);
 
 }

+ 0 - 81
cpp-admin/src/main/java/com/cpp/web/domain/station/WeatherStationStatusData.java

@@ -45,87 +45,6 @@ public class WeatherStationStatusData extends BaseCppEntity {
     @ApiModelProperty(value = "时间")
     private Date time;
 
-
-    /**
-     * 备用字段1
-     */
-    @ApiModelProperty(value = "备用字段1")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data1 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段2
-     */
-    @ApiModelProperty(value = "备用字段2")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data2 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段3
-     */
-    @ApiModelProperty(value = "备用字段3")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data3 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段4
-     */
-    @ApiModelProperty(value = "备用字段4")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data4 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段5
-     */
-    @ApiModelProperty(value = "备用字段5")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data5 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段6
-     */
-    @ApiModelProperty(value = "备用字段6")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data6 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段7
-     */
-    @ApiModelProperty(value = "备用字段7")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data7 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段8
-     */
-    @ApiModelProperty(value = "备用字段8")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data8 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段9
-     */
-    @ApiModelProperty(value = "备用字段9")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data9 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段10
-     */
-    @ApiModelProperty(value = "备用字段10")
-    @Digits(integer = 10, fraction = 2)
-    private BigDecimal data10 = new BigDecimal(-99);
-
-
     /**
      * 总辐射(W/㎡)
      */

+ 0 - 80
cpp-admin/src/main/java/com/cpp/web/domain/station/WindTowerStatusData.java

@@ -47,86 +47,6 @@ public class WindTowerStatusData extends BaseCppEntity {
 
 
     /**
-     * 备用字段1
-     */
-    @ApiModelProperty(value = "备用字段1")
-    @Digits(integer = 10, fraction = 4)
-    private BigDecimal data1 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段2
-     */
-    @ApiModelProperty(value = "备用字段2")
-    @Digits(integer = 10, fraction = 4)
-    private BigDecimal data2 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段3
-     */
-    @ApiModelProperty(value = "备用字段3")
-    @Digits(integer = 10, fraction = 4)
-    private BigDecimal data3 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段4
-     */
-    @ApiModelProperty(value = "备用字段4")
-    @Digits(integer = 10, fraction = 4)
-    private BigDecimal data4 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段5
-     */
-    @ApiModelProperty(value = "备用字段5")
-    @Digits(integer = 10, fraction = 4)
-    private BigDecimal data5 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段6
-     */
-    @ApiModelProperty(value = "备用字段6")
-    @Digits(integer = 10, fraction = 4)
-    private BigDecimal data6 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段7
-     */
-    @ApiModelProperty(value = "备用字段7")
-    @Digits(integer = 10, fraction = 4)
-    private BigDecimal data7 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段8
-     */
-    @ApiModelProperty(value = "备用字段8")
-    @Digits(integer = 10, fraction = 4)
-    private BigDecimal data8 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段9
-     */
-    @ApiModelProperty(value = "备用字段9")
-    @Digits(integer = 10, fraction = 4)
-    private BigDecimal data9 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段10
-     */
-    @ApiModelProperty(value = "备用字段10")
-    @Digits(integer = 10, fraction = 4)
-    private BigDecimal data10 = new BigDecimal(-99);
-
-
-    /**
      * 温度瞬时值
      */
     @ApiModelProperty(value = "温度瞬时值(℃)")

+ 0 - 70
cpp-admin/src/main/java/com/cpp/web/domain/station/WindTurbineStatusData.java

@@ -47,76 +47,6 @@ public class WindTurbineStatusData extends BaseCppEntity {
 
 
     /**
-     * 备用字段1
-     */
-    @ApiModelProperty(value = "备用字段1")
-    private BigDecimal data1 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段2
-     */
-    @ApiModelProperty(value = "备用字段2")
-    private BigDecimal data2 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段3
-     */
-    @ApiModelProperty(value = "备用字段3")
-    private BigDecimal data3 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段4
-     */
-    @ApiModelProperty(value = "备用字段4")
-    private BigDecimal data4 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段5
-     */
-    @ApiModelProperty(value = "备用字段5")
-    private BigDecimal data5 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段6
-     */
-    @ApiModelProperty(value = "备用字段6")
-    private BigDecimal data6 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段7
-     */
-    @ApiModelProperty(value = "备用字段7")
-    private BigDecimal data7 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段8
-     */
-    @ApiModelProperty(value = "备用字段8")
-    private BigDecimal data8 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段9
-     */
-    @ApiModelProperty(value = "备用字段9")
-    private BigDecimal data9 = new BigDecimal(-99);
-
-
-    /**
-     * 备用字段10
-     */
-    @ApiModelProperty(value = "备用字段10")
-    private BigDecimal data10 = new BigDecimal(-99);
-
-
-    /**
      * 有功(KW)
      */
     @ApiModelProperty(value = "有功(KW)")

+ 17 - 0
cpp-admin/src/main/java/com/cpp/web/mapper/AbnormalAlarmMapper.java

@@ -0,0 +1,17 @@
+package com.cpp.web.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cpp.web.domain.AbnormalAlarm;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 告警信息 mapper
+ *
+ * @author tl
+ * @date 2022-05-11 09:47:21
+ */
+@Mapper
+public interface AbnormalAlarmMapper extends BaseMapper<AbnormalAlarm> {
+
+}

+ 15 - 0
cpp-admin/src/main/java/com/cpp/web/mapper/station/ForecastPowerShortTermRegulationMapper.java

@@ -0,0 +1,15 @@
+package com.cpp.web.mapper.station;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cpp.web.domain.station.ForecastPowerShortTermRegulation;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * cpp_forecast_power_short_term_his
+ *
+ * @author tl
+ * @date 2024-09-23 15:28:33
+ */
+@Mapper
+public interface ForecastPowerShortTermRegulationMapper extends BaseMapper<ForecastPowerShortTermRegulation> {
+
+}

+ 15 - 0
cpp-admin/src/main/java/com/cpp/web/mapper/station/ForecastPowerUltraShortTermRegulationMapper.java

@@ -0,0 +1,15 @@
+package com.cpp.web.mapper.station;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cpp.web.domain.station.ForecastPowerUltraShortTermRegulation;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * cpp_forecast_power_ultra_short_term_his
+ *
+ * @author tl
+ * @date 2024-09-23 15:28:33
+ */
+@Mapper
+public interface ForecastPowerUltraShortTermRegulationMapper extends BaseMapper<ForecastPowerUltraShortTermRegulation> {
+
+}

+ 15 - 0
cpp-admin/src/main/java/com/cpp/web/service/AbnormalAlarmService.java

@@ -0,0 +1,15 @@
+package com.cpp.web.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cpp.web.domain.AbnormalAlarm;
+
+/**
+ * 告警信息业务层接口
+ *
+ * @author tl
+ * @date 2022-05-11 09:51:21
+ */
+public interface AbnormalAlarmService extends IService<AbnormalAlarm> {
+
+
+}

+ 572 - 0
cpp-admin/src/main/java/com/cpp/web/service/cloud/CloudFileParsing.java

@@ -0,0 +1,572 @@
+package com.cpp.web.service.cloud;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.NumberUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.RuntimeUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.ftp.Ftp;
+import cn.hutool.extra.ftp.FtpConfig;
+import cn.hutool.extra.ftp.FtpMode;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cpp.common.utils.StringUtils;
+import com.cpp.web.domain.AbnormalAlarm;
+import com.cpp.web.domain.cloud.ForecastPowerShortTermCloud;
+import com.cpp.web.domain.cloud.NwpCloud;
+import com.cpp.web.domain.datafactory.ParsingFileUrl;
+import com.cpp.web.domain.datafactory.ParsingLog;
+import com.cpp.web.domain.datafactory.ParsingType;
+import com.cpp.web.domain.datafactory.dto.ParsingResultDto;
+import com.cpp.web.domain.datafactory.enums.FileTypeEnum;
+import com.cpp.web.domain.enums.AlarmEnum;
+import com.cpp.web.domain.enums.DataSourcesEnum;
+import com.cpp.web.mapper.datafactory.ParsingTypeMapper;
+import com.cpp.web.service.AbnormalAlarmService;
+import com.cpp.web.service.datafactory.ParsingFileUrlService;
+import com.cpp.web.service.datafactory.ParsingInterface;
+import com.cpp.web.service.datafactory.ParsingLogService;
+import com.cpp.web.utils.DateTimeUtil;
+import com.cpp.web.utils.MessageUtils;
+import com.cpp.web.utils.NumberUtils;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang3.time.DateFormatUtils;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.stereotype.Service;
+
+import java.io.*;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * ftp文件解析
+ *
+ * @author tl
+ * @date 2022-05-11 09:51:21
+ */
+@AllArgsConstructor
+@Slf4j
+@Service
+public class CloudFileParsing {
+
+    private final ParsingLogService parsingLogService;
+
+    private final AbnormalAlarmService abnormalAlarmService;
+
+    private final ForecastPowerShortTermCloudService forecastPowerShortTermCloudService;
+    private final NwpCloudService nwpCloudService;
+
+    private final String PARSING_FILE_NEW_DIR = "/";
+
+    private final File fileNewDir = new File(PARSING_FILE_NEW_DIR);
+
+    private final ThreadPoolTaskExecutor executor;
+
+    /**
+     * 解析文件方法
+     * 逻辑:先配置识别文件名称类型:识别文件名称关键字对应的文件类型
+     * 有文件类型的配置才可以进入下一步
+     * <p>
+     * 查找各场站配置的ftp目录,去下载文件并识别文件类型执行对应的解析策略
+     * <p>
+     * 必要条件:1.配置文件识别类型。2.配置下载路径。3.配置解析公式
+     *
+     * @param
+     * @return
+     */
+    @Scheduled(fixedRate = 300000L)
+    public void parsingFile() {
+        {
+            log.info("-----------------开始执行预测文件解析任务----------------------");
+            Long currentDate = DateTimeUtil.getMillisecondsSubDay();//今日凌晨
+            boolean flag = false;
+
+            //判断该目录是否存在,不存在时创建
+            if (!fileNewDir.exists()) {
+                fileNewDir.mkdirs();
+                log.info("【" + fileNewDir.getPath() + "】目录不存在,系统自动创建文件目录");
+            }
+            log.info("系统扫描路径【" + fileNewDir.getPath() + "】");
+            // 获取指定目录下的文件
+            Collection<File> files = FileUtils.listFiles(fileNewDir, new String[]{"RB", "txt"}, false);
+            //当前时间格式化为年月日
+            String dayStr = new SimpleDateFormat("yyyyMMdd").format(new Date());
+
+
+            // 如果指定目录下有文件
+            if (files.size() > 0) {
+
+                List<ParsingLog> parsingLogs = new ArrayList<>();
+                List<AbnormalAlarm> abnormalAlarms = new ArrayList<>();
+
+                // 循环文件并解析
+                for (File file : files) {
+                    ParsingLog parsingLog = new ParsingLog();
+                    flag = false;
+
+                    String fileName = file.getName();
+
+                    parsingLog.setDataSources(DataSourcesEnum.E2);
+                    parsingLog.setParsingTime(new Date());
+                    parsingLog.setFileName(fileName);
+
+                    // 如果文件不是当然的,删除文件
+                    if (!fileName.contains(dayStr)) {
+                        file.delete();
+                        log.warn(fileName + "不是当天的文件,删除!");
+                        break;
+                    }
+                    // 如果文件名长度符合规则
+                    if (fileName.length() < 30) {
+                        // 如果是短期文件
+                        if (file.getName().startsWith("DQ")) {
+                            try {
+                                parsingLog.setFileType(FileTypeEnum.dq);
+                                // 解析短期文件
+                                List<ForecastPowerShortTermCloud> listDq = fileAnalysisShortTerm(file, new Date(currentDate));
+                                if (!listDq.isEmpty()) {
+                                    try {
+                                        parsingLog.setStationCode(listDq.get(0).getStationCode());
+                                        forecastPowerShortTermCloudService.saveBatch(listDq);
+                                        flag = true;
+                                    } catch (Exception e) {
+                                        log.error("保存短期数据报错:"+fileName, e);
+                                        parsingLog.setParsingDescribe("保存短期数据报错:"+fileName);
+                                        flag = false;
+                                    }
+                                } else {
+                                    log.info(file.getName() + "文件数据内容为空、不能正常解析 、移除该文件:"+fileName);
+                                    parsingLog.setParsingDescribe("文件数据内容为空、不能正常解析 、移除该文件:"+fileName);
+                                    flag = false;
+                                }
+
+
+                            } catch (Exception e) {
+                                flag = false;
+                                parsingLog.setParsingDescribe("解析DQ文件异常:"+fileName);
+                                log.error("解析DQ文件失败:"+fileName, e);
+                            }
+                        }
+
+
+                        if (file.getName().startsWith("NWP")) {
+                            try {
+                                parsingLog.setFileType(FileTypeEnum.nwp);
+                                List<NwpCloud> listNwp = fileAnalysisNwp(file,new Date(currentDate));
+                                if (!listNwp.isEmpty()) {
+                                    try {
+                                        parsingLog.setStationCode(listNwp.get(0).getStationCode());
+                                        nwpCloudService.saveBatch(listNwp);
+                                        flag = true;
+                                    } catch (Exception e) {
+                                        log.error("保存NWP数据报错:"+fileName, e);
+                                        parsingLog.setParsingDescribe("保存NWP数据报错:"+fileName);
+                                        flag = false;
+                                    }
+                                } else {
+                                    parsingLog.setParsingDescribe("文件数据内容为空、不能正常解析 、移除该文件:"+fileName);
+                                    log.info(file.getName() + "文件数据内容为空、不能正常解析 、移除该文件");
+                                    flag = false;
+                                }
+                            } catch (Exception e) {
+                                log.error("解析NWP文件失败:"+fileName, e);
+                                parsingLog.setParsingDescribe("解析NWP文件失败:"+fileName);
+                                flag = false;
+                            }
+                        }
+
+
+                        if (flag) {
+                            parsingLog.setParsingFileStatus("成功");
+                        } else {
+                            parsingLog.setParsingFileStatus("失败");
+                            abnormalAlarms.add(new AbnormalAlarm(DataSourcesEnum.E2,AlarmEnum.E4,parsingLog.getParsingDescribe(),""));
+                            //移除文件备份到error文件下
+                            moveFileError(file);
+                        }
+                        parsingLogs.add(parsingLog);
+                    }
+                }
+                if (parsingLogs.size()>0){
+                    parsingLogService.saveBatch(parsingLogs);
+                }
+                if (abnormalAlarms.size()>0){
+                    abnormalAlarmService.saveBatch(abnormalAlarms);
+                }
+            }
+
+
+            log.info("-----------------执行预测文件解析任务完成----------------------");
+        }
+
+    }
+
+
+    /**
+     * NWP解析
+     *
+     * @param file 文件路径
+     * @return 样例集合
+     */
+    private List<NwpCloud> fileAnalysisNwp(File file, Date currentDate) {
+        List<NwpCloud> listNwp = new ArrayList<>();
+        if (file.renameTo(file)) {
+            InputStreamReader readNwp = null;
+            BufferedReader bufferedReaderNwp = null;
+            try {
+                readNwp = new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8);//考虑到编码格式
+                bufferedReaderNwp = new BufferedReader(readNwp);
+                String lineTxt;
+                NwpCloud nwpData;
+                BigDecimal nwpDirectRadiation = new BigDecimal("0.7"); //直接辐射
+                BigDecimal nwpDiffuseRadiation = new BigDecimal("0.3"); //散接辐射
+
+
+                String stationCode = "";
+                String forecastModel = "";
+
+
+                while ((lineTxt = bufferedReaderNwp.readLine()) != null) {
+                    //NWP文件按照Tab方式截取
+                    String[] datas = lineTxt.split("\t");
+
+                    if (datas.length == 4 && datas[0].startsWith("<集中")) {
+                        // 使用单引号分割字符串
+                        stationCode = datas[1].split("'")[1];
+                        forecastModel = datas[2].split("'")[1];
+                    }
+
+
+                    if (!stationCode.equals("")&&!forecastModel.equals("")&&datas.length >= 35 && datas[0].startsWith("#")) {
+                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                        //过滤当天的数据
+                        //if (sdf.parse(datas[5]).getTime() >= TimeUtils.getMillisecondsSubDay() + 24 * 60 * 60 *
+                        // 1000) {
+
+
+                        Date time = sdf.parse(datas[5]);
+                        Integer howLongAgo = calcHowLongAgo(currentDate, time);
+                        if (howLongAgo > 0) {
+
+                            nwpData = new NwpCloud();
+
+                            //将截取的文件放入nwpData中
+                            nwpData.setForecastHowLongAgo(howLongAgo);
+                            nwpData.setForecastModel(forecastModel);
+                            nwpData.setStationCode(stationCode);
+                            nwpData.setTime(time);//采集时间 与 短期预测时间关联
+                            nwpData.setT(NumberUtils.subtract(new BigDecimal(datas[6]), new BigDecimal("273.15")));//温度
+
+                            nwpData.setSenf(new BigDecimal(datas[11]).setScale(2, RoundingMode.HALF_UP));//感热
+                            nwpData.setSwr(new BigDecimal(datas[9]).setScale(2, RoundingMode.HALF_UP));//短波辐射(相当于总辐射)
+                            nwpData.setLwr(new BigDecimal(datas[10]).setScale(2, RoundingMode.HALF_UP));//短波辐射(相当于总辐射)
+                            nwpData.setPressure(new BigDecimal(datas[8]).setScale(2, RoundingMode.HALF_UP));//地表气压
+                            nwpData.setRh(new BigDecimal(datas[7]).setScale(2, RoundingMode.HALF_UP));//2m相对湿度
+                            nwpData.setDiffuseRadiation(new BigDecimal(datas[9]).multiply(nwpDiffuseRadiation).setScale(2, RoundingMode.HALF_UP));//散接辐射
+                            nwpData.setDirectRadiation(new BigDecimal(datas[9]).multiply(nwpDirectRadiation).setScale(2, RoundingMode.HALF_UP));//直接辐射
+
+                            nwpData.setWs10(new BigDecimal(datas[19]).setScale(2, RoundingMode.HALF_UP));
+                            nwpData.setWs30(new BigDecimal(datas[20]).setScale(2, RoundingMode.HALF_UP));
+                            nwpData.setWs50(new BigDecimal(datas[21]).setScale(2, RoundingMode.HALF_UP));
+                            nwpData.setWs70(new BigDecimal(datas[22]).setScale(2, RoundingMode.HALF_UP));
+                            nwpData.setWs80(new BigDecimal(datas[23]).setScale(2, RoundingMode.HALF_UP));
+                            nwpData.setWs90(new BigDecimal(datas[24]).setScale(2, RoundingMode.HALF_UP));
+                            nwpData.setWs100(new BigDecimal(datas[25]).setScale(2, RoundingMode.HALF_UP));
+                            nwpData.setWs170(new BigDecimal(datas[26]).setScale(2, RoundingMode.HALF_UP));
+                            nwpData.setWd10(new BigDecimal(datas[27]).setScale(2, RoundingMode.HALF_UP));
+                            nwpData.setWd30(new BigDecimal(datas[28]).setScale(2, RoundingMode.HALF_UP));
+                            nwpData.setWd50(new BigDecimal(datas[29]).setScale(2, RoundingMode.HALF_UP));
+                            nwpData.setWd70(new BigDecimal(datas[30]).setScale(2, RoundingMode.HALF_UP));
+                            nwpData.setWd80(new BigDecimal(datas[31]).setScale(2, RoundingMode.HALF_UP));
+                            nwpData.setWd90(new BigDecimal(datas[32]).setScale(2, RoundingMode.HALF_UP));
+                            nwpData.setWd100(new BigDecimal(datas[33]).setScale(2, RoundingMode.HALF_UP));
+                            nwpData.setWd170(new BigDecimal(datas[34]).setScale(2, RoundingMode.HALF_UP));
+                            if (datas.length > 35) {
+                                //nwp 新增解析内容
+                                nwpData.setWs20(new BigDecimal(datas[35]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWs40(new BigDecimal(datas[36]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWs60(new BigDecimal(datas[37]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWs110(new BigDecimal(datas[38]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWs120(new BigDecimal(datas[39]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWs130(new BigDecimal(datas[40]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWs140(new BigDecimal(datas[41]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWs150(new BigDecimal(datas[42]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWs160(new BigDecimal(datas[43]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWs180(new BigDecimal(datas[44]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWs190(new BigDecimal(datas[45]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWs200(new BigDecimal(datas[46]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWd20(new BigDecimal(datas[47]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWd40(new BigDecimal(datas[48]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWd60(new BigDecimal(datas[49]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWd110(new BigDecimal(datas[50]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWd120(new BigDecimal(datas[51]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWd130(new BigDecimal(datas[52]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWd140(new BigDecimal(datas[53]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWd150(new BigDecimal(datas[54]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWd160(new BigDecimal(datas[55]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWd180(new BigDecimal(datas[56]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWd190(new BigDecimal(datas[57]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setWd200(new BigDecimal(datas[58]).setScale(2, RoundingMode.HALF_UP));
+                                //下面的感觉用不上,先注释
+//                            nwpData.setT10(new BigDecimal(datas[59]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT20(new BigDecimal(datas[60]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT30(new BigDecimal(datas[61]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT40(new BigDecimal(datas[62]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT50(new BigDecimal(datas[63]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT60(new BigDecimal(datas[64]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT70(new BigDecimal(datas[65]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT80(new BigDecimal(datas[66]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT90(new BigDecimal(datas[67]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT100(new BigDecimal(datas[68]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT110(new BigDecimal(datas[69]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT120(new BigDecimal(datas[70]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT130(new BigDecimal(datas[71]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT140(new BigDecimal(datas[72]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT150(new BigDecimal(datas[73]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT160(new BigDecimal(datas[74]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT170(new BigDecimal(datas[75]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT180(new BigDecimal(datas[76]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT190(new BigDecimal(datas[77]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setT200(new BigDecimal(datas[78]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setDniCalcd(new BigDecimal(datas[79]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setSolarZenith(new BigDecimal(datas[80]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setClearskyGhi(new BigDecimal(datas[81]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setLcc(new BigDecimal(datas[82]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setMcc(new BigDecimal(datas[83]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setHcc(new BigDecimal(datas[84]).setScale(2, RoundingMode.HALF_UP));
+//                            nwpData.setTcc(new BigDecimal(datas[85]).setScale(2, RoundingMode.HALF_UP));
+                                nwpData.setTpr(new BigDecimal(datas[86]).setScale(2, RoundingMode.HALF_UP));
+
+                            }
+                            listNwp.add(nwpData);
+                        }
+                    }
+                }
+            } catch (IOException | ParseException | RuntimeException e) {
+                log.error("系统错误:", e);
+                File destFile = new File(file.getPath().replaceFirst("new", "error"));
+                if (destFile.exists()) {
+                    destFile.delete();
+                }
+                try {
+                    FileUtils.moveFile(file, destFile);
+                } catch (IOException e1) {
+                    log.error(file.getName() + "文件解析失败", e);
+                }
+            } finally {
+                close(bufferedReaderNwp, readNwp);
+            }
+        }
+        return listNwp;
+    }
+
+    /**
+     * 短期解析
+     *
+     * @param file        文件路径
+     * @param currentDate 当前时间
+     * @return 样例集合
+     */
+    private List<ForecastPowerShortTermCloud> fileAnalysisShortTerm(File file, Date currentDate) {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        List<ForecastPowerShortTermCloud> forecastPowerShortTerm = new ArrayList<>();
+        // 当文件未被使用时,进行解析上报
+        if (file.renameTo(file)) {
+            InputStreamReader read = null;
+            BufferedReader bufferedReader = null;
+            String stringLine;
+            ForecastPowerShortTermCloud stf;
+            try {
+                read = new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8);
+                bufferedReader = new BufferedReader(read);
+
+                String stationCode = "";
+                String forecastModel = "";
+
+                // 循环解析文件
+                while ((stringLine = bufferedReader.readLine()) != null) {
+
+                    String[] string_arr = stringLine.split("\t");
+
+                    if (string_arr.length == 4) {
+
+                        if (string_arr[0].startsWith("<集中")) {
+                            // 使用单引号分割字符串
+                            stationCode = string_arr[1].split("'")[1];
+                            forecastModel = string_arr[2].split("'")[1];
+                        }
+
+                        if (!stationCode.equals("") && !forecastModel.equals("") && string_arr[0].startsWith("#")) {
+                            if (StringUtils.isNotEmpty(string_arr[2])) {
+                                Date time = sdf.parse(string_arr[2]);
+                                Integer howLongAgo = calcHowLongAgo(currentDate, time);
+                                if (howLongAgo > 0) {
+                                    stf = new ForecastPowerShortTermCloud();
+                                    stf.setFpValue(new BigDecimal(string_arr[3]));
+                                    stf.setTime(time);
+                                    stf.setForecastHowLongAgo(howLongAgo);
+                                    stf.setStationCode(stationCode);
+                                    stf.setForecastModel(forecastModel);
+                                    forecastPowerShortTerm.add(stf);
+                                }
+                            }
+                        }
+
+                    }
+                }
+
+
+            } catch (IOException | ParseException | RuntimeException e) {
+                log.error("系统错误:", e);
+                File destFile = new File(file.getPath().replaceFirst("new", "error"));
+                if (destFile.exists()) {
+                    destFile.delete();
+                }
+                try {
+                    FileUtils.moveFile(file, destFile);
+                } catch (IOException e1) {
+                    log.error(file.getName() + "文件解析失败", e);
+                }
+            } finally {
+                close(bufferedReader, read);
+            }
+        }
+        return forecastPowerShortTerm;
+    }
+
+
+    /**
+     * 关闭文件流
+     *
+     * @param bufferedReader 字符数据
+     * @param read           字节流
+     */
+    private void close(BufferedReader bufferedReader, InputStreamReader read) {
+        try {
+            if (bufferedReader != null) {
+                bufferedReader.close();
+            }
+            if (read != null) {
+                read.close();
+            }
+        } catch (IOException e) {
+            log.error("关闭文件流失败:", e);
+        }
+    }
+
+
+    /**
+     * 计算D+x中的x
+     *
+     * @param baseTime
+     * @param time
+     */
+    public Integer calcHowLongAgo(Date baseTime, Date time) {
+        return ((int) (time.getTime() - baseTime.getTime() % 86400000L)) + 1;
+    }
+
+
+    /**
+     * 移动文件到临时目录下
+     *
+     * @param file 文件
+     */
+    private void moveFile(File file) {
+        // 移动文件到处理目录
+        File destFile = new File(file.getPath().replaceFirst("new", "backupsTemp"));
+        log.info("move file :{}, dest file:{}", file, destFile);
+        if (destFile.exists()) {
+            destFile.delete();
+        }
+        try {
+            FileUtils.moveFile(file, destFile);
+        } catch (IOException e) {
+            log.error("系统移除文件错误:", e);
+        }
+        moveFileBackups(destFile.getParent());
+    }
+
+
+    /**
+     * 移动文件到处理目录
+     *
+     * @param filePath 文件路径
+     */
+    private void moveFileBackups(String filePath) {
+        String targetRoot = filePath.replaceFirst("backupsTemp", "backups");
+        String path = mkDirForTime(targetRoot, null);
+        path = mkDirForTime(path, "yyyy");
+        path = mkDirForTime(path, "MM");
+        path = mkDirForTime(path, "yyyyMMdd");
+        path = mkDirForTime(path, "HHmm");
+        // 移动文件夹内容
+        File sourceFile = new File(filePath);
+        if (sourceFile.exists()) {
+            try {
+                File[] files = sourceFile.listFiles();
+                if (files != null) {
+                    for (File f : files) {
+                        if (f.renameTo(new File(path + f.getName()))) {
+                            log.info("move file :{}, dest file:{}", path, f.getName());
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                log.error("文件移动失败" + e);
+            }
+        }
+    }
+
+    /**
+     * 创建备份文件夹
+     */
+    public static String mkDirForTime(String targetRoot, String format) {
+        String path;
+        File file;
+        if (StringUtils.isNotEmpty(format)) {
+            long current = System.currentTimeMillis();
+            path = DateFormatUtils.format(current, format);
+            file = new File(targetRoot + File.separator + path + File.separator);
+
+        } else {
+            file = new File(targetRoot + File.separator);
+        }
+
+        if (!file.exists() && !file.isFile()) {
+
+            if (file.mkdir()) {
+                log.info("已创建文件夹");
+            } else {
+                log.info("创建文件夹失败,路径:" + file.getPath());
+            }
+        }
+        return file.getPath() + File.separator;
+    }
+
+
+    /**
+     * 移动文件到处理错误目录下
+     *
+     * @param file 文件
+     */
+    private void moveFileError(File file) {
+        File destFile = new File(file.getPath().replaceFirst("new", "error"));
+        if (destFile.exists()) {
+            destFile.delete();
+        }
+        try {
+            FileUtils.moveFile(file, destFile);
+        } catch (IOException e) {
+            log.error(file.getName() + "文件解析失败", e);
+        }
+    }
+}

+ 1 - 2
cpp-admin/src/main/java/com/cpp/web/service/cloud/ForecastPowerShortTermCloudService.java

@@ -23,5 +23,4 @@ public interface ForecastPowerShortTermCloudService extends IService<ForecastPow
      */
     List<ForecastPowerShortTermCloud> findByStationCodeAndStartTimeAndEndTime(String stationCode, Date startTime, Date endTime);
 
-    List<ForecastPowerShortTermCloud> findByStationCodeAndStartTimeAndEndTimeAndForecastManufactor(String stationCode, Date startTime, Date endTime, String forecastManufactor);
-}
+    List<ForecastPowerShortTermCloud> findByStationCodeAndStartTimeAndEndTimeAndForecastManufactor(String stationCode, Date startTime, Date endTime, String forecastManufactor);}

+ 87 - 60
cpp-admin/src/main/java/com/cpp/web/service/datafactory/FtpFileParsing.java

@@ -1,32 +1,32 @@
 package com.cpp.web.service.datafactory;
 
-import cn.hutool.core.lang.Filter;
 import cn.hutool.extra.ftp.Ftp;
 import cn.hutool.extra.ftp.FtpConfig;
 import cn.hutool.extra.ftp.FtpMode;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cpp.web.domain.AbnormalAlarm;
 import com.cpp.web.domain.datafactory.ParsingFileUrl;
 import com.cpp.web.domain.datafactory.ParsingLog;
 import com.cpp.web.domain.datafactory.ParsingType;
 import com.cpp.web.domain.datafactory.dto.ParsingResultDto;
 import com.cpp.web.domain.datafactory.enums.FileTypeEnum;
-import com.cpp.web.domain.datafactory.enums.ParsingDataSourcesEnum;
-import com.cpp.web.mapper.datafactory.ParsingFileUrlMapper;
-import com.cpp.web.mapper.datafactory.ParsingLogMapper;
+import com.cpp.web.domain.enums.AlarmEnum;
+import com.cpp.web.domain.enums.DataSourcesEnum;
 import com.cpp.web.mapper.datafactory.ParsingTypeMapper;
+import com.cpp.web.service.AbnormalAlarmService;
+import com.cpp.web.utils.MessageUtils;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang3.time.DateFormatUtils;
-import org.apache.commons.net.ftp.FTPFile;
 import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Service;
 
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.nio.charset.Charset;
-import java.text.DateFormat;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -49,19 +49,23 @@ public class FtpFileParsing {
 
     private final ParsingLogService parsingLogService;
 
+    private final AbnormalAlarmService abnormalAlarmService;
+
     private final String PARSING_FILE_TEMP_DIR = "/";
     private final String PARSING_FILE_SUCCESS_DIR = "/";
     private final String PARSING_FILE_FAIL_DIR = "/";
 
     private final File fileTempDir = new File(PARSING_FILE_TEMP_DIR);
 
+    private final ThreadPoolTaskExecutor executor;
+
     /**
      * 解析文件方法
      * 逻辑:先配置识别文件名称类型:识别文件名称关键字对应的文件类型
      * 有文件类型的配置才可以进入下一步
      * <p>
      * 查找各场站配置的ftp目录,去下载文件并识别文件类型执行对应的解析策略
-     *
+     * <p>
      * 必要条件:1.配置文件识别类型。2.配置下载路径。3.配置解析公式
      *
      * @param
@@ -70,11 +74,14 @@ public class FtpFileParsing {
     @Scheduled(fixedRate = 300000L)
     public void parsingFile() {
 
+
+        log.info("-----------------开始执行FTP文件解析任务----------------------");
+
         List<ParsingType> parsingTypes = parsingTypeMapper.selectList(null);
 
         if (parsingTypes.size() > 0) {
 
-            List<ParsingFileUrl> fileUrls = parsingFileUrlService.list(Wrappers.lambdaQuery(ParsingFileUrl.class).eq(ParsingFileUrl::getParsingDataSources, ParsingDataSourcesEnum.E1));
+            List<ParsingFileUrl> fileUrls = parsingFileUrlService.list(Wrappers.lambdaQuery(ParsingFileUrl.class).eq(ParsingFileUrl::getParsingDataSources, DataSourcesEnum.E1));
 
             if (fileUrls.size() > 0) {
                 Map<FileTypeEnum, List<ParsingFileUrl>> fileTypeEnumListMap = fileUrls.stream().collect(Collectors.groupingBy(ParsingFileUrl::getFileType, Collectors.toList()));
@@ -82,80 +89,100 @@ public class FtpFileParsing {
                 Ftp ftp = createParsingFtp();
                 if (ftp != null) {
                     List<ParsingLog> parsingLogs = new ArrayList<>();
+                    List<AbnormalAlarm> abnormalAlarms = new ArrayList<>();
                     for (ParsingType parsingType : parsingTypes) {
                         if (fileTypeEnumListMap.containsKey(parsingType.getFileType())) {
-                            ParsingInterface parsingInterface = parsingInterfaceMap.get(parsingType.getFileType().name() + "Parsing");
-                            parsingInterface.activationParsingConf();//初始化解析配置
-                            List<ParsingFileUrl> fileUrlList = fileTypeEnumListMap.get(parsingType.getFileType());
-                            for (ParsingFileUrl parsingFileUrl : fileUrlList) {
-
-                                String ftpUrl = parsingFileUrl.getUrl();
-                                List<String> fileNames = ftp.ls(ftpUrl).stream().filter(f -> f.contains(parsingType.getFileName())).collect(Collectors.toList());
-                                if (fileNames.size() > 0) {
-                                    for (String fileName : fileNames) {
-                                        //下载文件到临时目录
-                                        ftp.download(ftpUrl, fileName, fileTempDir);
-                                        File file = FileUtils.getFile(fileTempDir, fileName);
-                                        ParsingLog parsingLog = new ParsingLog();
-                                        Date now = new Date();
-                                        parsingLog.setParsingTime(now);
-                                        ParsingResultDto parsingResultDto = parsingInterface.parsing(file, parsingFileUrl.getStationCode());
-                                        parsingLog.setParsingDescribe(parsingResultDto.getMessage());
-                                        parsingLog.setFileType(parsingType.getFileType());
-                                        if (parsingResultDto.getStatus().equals("fail")) {
-                                            try {
-                                                File failFileDir = new File(PARSING_FILE_FAIL_DIR + File.separator + DateFormatUtils.format(now, "yyyy-MM-DD"));
-                                                File failFile = new File(failFileDir.getPath() + File.separator + fileName);
-                                                if (failFile.exists()) {
-                                                    failFile.delete();
-                                                    log.error("已有过解析失败文件,错误文件将覆盖!场站编号:{},文件名称:{}", parsingFileUrl.getStationCode(), fileName);
-                                                }
-
-                                                FileUtils.moveFile(file, failFileDir);
-                                            } catch (IOException e) {
-                                                log.error("解析文件失败后文件移动失败!场站编号:{},文件名称:{}", parsingFileUrl.getStationCode(), fileName, e);
-                                                e.printStackTrace();
-                                            }
-                                            file.delete();//失败删除本地文件,等待下次下载
-                                            parsingLog.setParsingFileStatus("失败");
-                                        } else {
-                                            ftp.delFile(ftpUrl + "/" + fileName);//成功删除ftp上的文件
-
-                                            try {
-                                                File successFileDir = new File(PARSING_FILE_SUCCESS_DIR + File.separator + DateFormatUtils.format(now, "yyyy-MM-DD"));
-                                                File successFile = new File(successFileDir.getPath() + File.separator + fileName);
-                                                if (successFile.exists()) {
-                                                    successFile.delete();
-                                                    log.error("已有过解析成功文件,成功文件将覆盖!场站编号:{},文件名称:{}", parsingFileUrl.getStationCode(), fileName);
+                            executor.execute(new Runnable() {
+                                @Override
+                                public void run() {
+                                    ParsingInterface parsingInterface = parsingInterfaceMap.get(parsingType.getFileType().name() + "Parsing");
+                                    parsingInterface.activationParsingConf();//初始化解析配置
+                                    List<ParsingFileUrl> fileUrlList = fileTypeEnumListMap.get(parsingType.getFileType());
+                                    for (ParsingFileUrl parsingFileUrl : fileUrlList) {
+                                        String ftpUrl = parsingFileUrl.getUrl();
+                                        List<String> fileNames = ftp.ls(ftpUrl).stream().filter(f -> f.contains(parsingType.getFileName())).collect(Collectors.toList());
+                                        if (fileNames.size() > 0) {
+                                            for (String fileName : fileNames) {
+                                                try {
+                                                    //下载文件到临时目录
+                                                    ftp.download(ftpUrl, fileName, fileTempDir);
+                                                    File file = FileUtils.getFile(fileTempDir, fileName);
+                                                    ParsingLog parsingLog = new ParsingLog();
+                                                    Date now = new Date();
+                                                    parsingLog.setParsingTime(now);
+                                                    ParsingResultDto parsingResultDto = parsingInterface.parsing(file, parsingFileUrl.getStationCode());
+                                                    parsingLog.setParsingDescribe(parsingResultDto.getMessage());
+                                                    parsingLog.setFileType(parsingType.getFileType());
+                                                    parsingLog.setDataSources(DataSourcesEnum.E1);
+                                                    if (parsingResultDto.getStatus().equals("fail")) {
+                                                        try {
+                                                            File failFileDir = new File(PARSING_FILE_FAIL_DIR + File.separator + DateFormatUtils.format(now, "yyyy-MM-DD"));
+                                                            File failFile = new File(failFileDir.getPath() + File.separator + fileName);
+                                                            if (failFile.exists()) {
+                                                                failFile.delete();
+                                                                log.error("已有过解析失败文件,错误文件将覆盖!场站编号:{},文件名称:{}", parsingFileUrl.getStationCode(), fileName);
+                                                            }
+
+                                                            FileUtils.moveFile(file, failFileDir);
+                                                        } catch (IOException e) {
+                                                            log.error("解析文件失败后文件移动失败!场站编号:{},文件名称:{}", parsingFileUrl.getStationCode(), fileName, e);
+                                                            e.printStackTrace();
+                                                        }
+                                                        file.delete();//失败删除本地文件,等待下次下载
+                                                        parsingLog.setParsingFileStatus("失败");
+
+                                                        abnormalAlarms.add(new AbnormalAlarm(DataSourcesEnum.E3, AlarmEnum.E4, MessageUtils.format("无法解析场站端文件:{}",fileName), parsingFileUrl.getStationCode()));
+
+                                                    } else {
+                                                        ftp.delFile(ftpUrl + "/" + fileName);//成功删除ftp上的文件
+
+                                                        try {
+                                                            File successFileDir = new File(PARSING_FILE_SUCCESS_DIR + File.separator + DateFormatUtils.format(now, "yyyy-MM-DD"));
+                                                            File successFile = new File(successFileDir.getPath() + File.separator + fileName);
+                                                            if (successFile.exists()) {
+                                                                successFile.delete();
+                                                                log.error("已有过解析成功文件,成功文件将覆盖!场站编号:{},文件名称:{}", parsingFileUrl.getStationCode(), fileName);
+                                                            }
+
+                                                            FileUtils.moveFile(file, successFileDir);
+                                                        } catch (IOException e) {
+                                                            log.error("解析文件成功后文件移动失败!场站编号:{},文件名称:{}", parsingFileUrl.getStationCode(), fileName, e);
+                                                            e.printStackTrace();
+                                                        }
+                                                        file.delete();//失败删除本地文件,等待下次下载
+                                                        parsingLog.setParsingFileStatus("成功");
+                                                    }
+                                                    parsingLogs.add(parsingLog);
+                                                } catch (Exception e) {
+                                                    abnormalAlarms.add(new AbnormalAlarm(DataSourcesEnum.E3, AlarmEnum.E4, MessageUtils.format("无法解析场站端文件:{}",fileName), parsingFileUrl.getStationCode()));
+                                                    log.error("下载并解析文件{}时异常", fileName, e);
                                                 }
 
-                                                FileUtils.moveFile(file, successFileDir);
-                                            } catch (IOException e) {
-                                                log.error("解析文件成功后文件移动失败!场站编号:{},文件名称:{}", parsingFileUrl.getStationCode(), fileName, e);
-                                                e.printStackTrace();
                                             }
-                                            file.delete();//失败删除本地文件,等待下次下载
-                                            parsingLog.setParsingFileStatus("成功");
                                         }
-                                        parsingLogs.add(parsingLog);
                                     }
                                 }
-                            }
+                            });
                         }
                     }
 
+                    parsingLogService.saveBatch(parsingLogs);
+
                     try {
                         ftp.close();
                     } catch (IOException e) {
                         e.printStackTrace();
                     }
-                    parsingLogService.saveBatch(parsingLogs);
+
+                    abnormalAlarmService.saveBatch(abnormalAlarms);
                 }
 
             }
         } else {
             log.info("未配置文件识别类型标识,无法进行下载解析");
         }
+
+        log.info("-----------------执行FTP文件解析任务完成----------------------");
     }
 
     public Ftp createParsingFtp() {

+ 14 - 22
cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingCdqServiceImpl.java

@@ -1,17 +1,13 @@
 package com.cpp.web.service.datafactory.impl;
 
-import cn.hutool.core.date.DateUtil;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.cpp.web.domain.datafactory.BaseParsing;
 import com.cpp.web.domain.datafactory.ParsingCdq;
-import com.cpp.web.domain.datafactory.ParsingDq;
 import com.cpp.web.domain.datafactory.dto.ParsingConfParam;
 import com.cpp.web.domain.datafactory.dto.ParsingResultDto;
 import com.cpp.web.domain.datafactory.enums.FileTypeEnum;
-import com.cpp.web.domain.station.ForecastPowerShortTermStation;
 import com.cpp.web.domain.station.ForecastPowerUltraShortTermStation;
 import com.cpp.web.mapper.datafactory.ParsingCdqMapper;
-import com.cpp.web.service.cloud.ForecastPowerUltraShortTermCloudService;
 import com.cpp.web.service.datafactory.ParsingCdqService;
 import com.cpp.web.service.datafactory.ParsingInterface;
 import com.cpp.web.service.station.ForecastPowerUltraShortTermStationService;
@@ -26,7 +22,6 @@ import org.springframework.transaction.annotation.Transactional;
 import java.io.File;
 import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
-import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
@@ -80,42 +75,40 @@ public class ParsingCdqServiceImpl extends ServiceImpl<ParsingCdqMapper, Parsing
                         if (parsingCdq.getFpValue() != null) {
                             List<BigDecimal> fpValues = parsingFpValue(parsingCdq.getFpValue(), fileContent);
                             if (fpValues.size() > 0) {
+                                BigDecimal openCapacity = parsingValue(parsingCdq.getOpenCapacity(),fileContent);
                                 for (BigDecimal fpValue : fpValues) {
                                     ForecastPowerUltraShortTermStation forecastPowerUltraShortTermStation = new ForecastPowerUltraShortTermStation();
                                     forecastPowerUltraShortTermStation.setStationCode(stationCode);
                                     forecastPowerUltraShortTermStation.setFpValue(fpValue);
                                     forecastPowerUltraShortTermStation.setTime(time);
                                     forecastPowerUltraShortTermStation.setForecastHowLongAgo(calcHowLongAgo(forecastTime, time));
+                                    forecastPowerUltraShortTermStation.setOpenCapacity(openCapacity);
                                     forecastPowerUltraShortTermStationList.add(forecastPowerUltraShortTermStation);
                                     time = new Date(time.getTime() + 900000L);//递增15分钟
                                 }
                                 forecastPowerUltraShortTermStationService.saveBatch(forecastPowerUltraShortTermStationList);
-                                log.info("解析DQ文件:{} 成功! O(∩_∩)O", file.getName());
+                                log.info("解析CDQ文件:{} 成功! O(∩_∩)O", file.getName());
                                 parsingResultDto.setStatus("success");
                             } else {
-                                parsingResultDto.setMessage("解析短期文件时间错误");
-                                log.error("解析DQ文件时间错误");
+                                parsingResultDto.setMessage("解析短期文件时间错误");
+                                log.error("解析CDQ文件时间错误");
                             }
                         } else {
-                            parsingResultDto.setMessage("短期文件里日期不对");
-                            log.error("dq文件里日期不对");
+                            parsingResultDto.setMessage("短期文件里日期不对");
+                            log.error("cdq文件里日期不对");
                         }
-
                     } else {
-                        parsingResultDto.setMessage("解析短期文件无数据");
-                        log.error("解析短期文件无数据");
+                        parsingResultDto.setMessage("解析短期文件无数据");
+                        log.error("解析短期文件无数据");
                     }
-
                 }
-
-
             } else {
-                parsingResultDto.setMessage("短期暂无单行解析方式");
-                log.error("dq暂无单行解析方式");
+                parsingResultDto.setMessage("超短期暂无单行解析方式");
+                log.error("cdq暂无单行解析方式");
             }
         } catch (Exception e) {
-            parsingResultDto.setMessage("解析短期数据失败!");
-            log.error("解析短期数据失败! /(ㄒoㄒ)/~~", e);
+            parsingResultDto.setMessage("解析短期数据失败!");
+            log.error("解析短期数据失败! /(ㄒoㄒ)/~~", e);
         } finally {
             return parsingResultDto;
         }
@@ -176,7 +169,7 @@ public class ParsingCdqServiceImpl extends ServiceImpl<ParsingCdqMapper, Parsing
      *   4-20:取值在4-20行
      *   3:第三列
      * */
-    protected List<BigDecimal> parsingFpValue(String sign, List<String> fileContent) {
+    private List<BigDecimal> parsingFpValue(String sign, List<String> fileContent) {
         List<BigDecimal> fpValues = new ArrayList<>();
         try {
             ParsingConfParam config = ParsingFieldUtil.getConfig(sign);
@@ -214,7 +207,6 @@ public class ParsingCdqServiceImpl extends ServiceImpl<ParsingCdqMapper, Parsing
     }
 
 
-
     public List<ParsingCdq> selectByStationCode(String stationCode) {
         return this.parsingCdqs.stream().filter(p -> p.getStationCode().equals(stationCode)).collect(Collectors.toList());
     }

+ 3 - 3
cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingCftServiceImpl.java

@@ -137,9 +137,9 @@ public class ParsingCftServiceImpl extends ServiceImpl<ParsingCftMapper, Parsing
 
     @Override
     public boolean activationParsingConf() {
-        this.parsingCfts = baseMapper.selectList(null);
-        this.windTowerInfos = windTowerInfoService.list(null);
-        return false;
+        this.parsingCfts = list();
+        this.windTowerInfos = windTowerInfoService.list();
+        return true;
     }
 
 

+ 47 - 14
cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingDqServiceImpl.java

@@ -56,7 +56,7 @@ public class ParsingDqServiceImpl extends ServiceImpl<ParsingDqMapper, ParsingDq
 
     @Override
     public boolean activationParsingConf() {
-        this.parsingDqs = baseMapper.selectList(null);
+        this.parsingDqs = list();
         return true;
     }
 
@@ -81,15 +81,24 @@ public class ParsingDqServiceImpl extends ServiceImpl<ParsingDqMapper, ParsingDq
                         if (parsingDqInfo.getFpValue() != null) {
                             List<BigDecimal> fpValues = parsingFpValue(parsingDqInfo.getFpValue(), fileContent);
                             if (fpValues.size() > 0) {
+                                BigDecimal capacity = parsingValue(parsingDqInfo.getCapacity(), fileContent);
                                 for (BigDecimal fpValue : fpValues) {
                                     ForecastPowerShortTermStation forecastPowerShortTermStation = new ForecastPowerShortTermStation();
                                     forecastPowerShortTermStation.setStationCode(stationCode);
                                     forecastPowerShortTermStation.setFpValue(fpValue);
                                     forecastPowerShortTermStation.setTime(time);
                                     forecastPowerShortTermStation.setForecastHowLongAgo(calcHowLongAgo(forecastTime, time));
+                                    forecastPowerShortTermStation.setCapacity(capacity);
                                     forecastPowerShortTermStationList.add(forecastPowerShortTermStation);
                                     time = new Date(time.getTime() + 900000L);//递增15分钟
                                 }
+
+                                List<BigDecimal> openCapacityList = parsingOpenCapacityValue(parsingDqInfo.getOpenCapacity(), fileContent);
+                                if (openCapacityList != null && openCapacityList.size() == fpValues.size()) {
+                                    for (int i = 0; i < forecastPowerShortTermStationList.size(); i++) {
+                                        forecastPowerShortTermStationList.get(i).setOpenCapacity(openCapacityList.get(i));
+                                    }
+                                }
                                 forecastPowerShortTermStationService.saveBatch(forecastPowerShortTermStationList);
                                 log.info("解析DQ文件:{} 成功! O(∩_∩)O", file.getName());
                                 parsingResultDto.setStatus("success");
@@ -167,32 +176,56 @@ public class ParsingDqServiceImpl extends ServiceImpl<ParsingDqMapper, ParsingDq
      *   4-20:取值在4-20行
      *   3:第三列
      * */
-    protected List<BigDecimal> parsingFpValue(String sign, List<String> fileContent) {
+    private List<BigDecimal> parsingFpValue(String sign, List<String> fileContent) {
         List<BigDecimal> fpValues = new ArrayList<>();
         try {
-            ParsingConfParam config = ParsingFieldUtil.getConfig(sign);
+            parsingValues(sign, fileContent, fpValues);
 
+            log.info("解析短期【预测数据】成功!!!==》记录数:{}", fpValues.size());
+        } catch (RuntimeException e) {
+            log.error("解析短期【预测数据】失败");
+            e.printStackTrace();
+        } finally {
+            return fpValues;
+        }
+    }
 
-            String[] lineNumber = config.getLineNumber().split("-");
-            int startLine = ParsingUtil.noParseInt(lineNumber[0]);
-            int endLine = ParsingUtil.noParseInt(lineNumber[1]);
+    private void parsingValues(String sign, List<String> fileContent, List<BigDecimal> fpValues) {
+        ParsingConfParam config = ParsingFieldUtil.getConfig(sign);
 
-            for (int i = startLine; i <= endLine; i++) {
-                String[] strings = ParsingUtil.splitLineWithSpace(fileContent.get(i));
-                String result = strings[ParsingUtil.noParseInt(config.getRowNumber())];
 
-                fpValues.add(new BigDecimal(result));
-            }
+        String[] lineNumber = config.getLineNumber().split("-");
+        int startLine = ParsingUtil.noParseInt(lineNumber[0]);
+        int endLine = ParsingUtil.noParseInt(lineNumber[1]);
 
-            log.info("解析短期【预测数据】成功!!!==》记录数:{}", fpValues.size());
+        for (int i = startLine; i <= endLine; i++) {
+            String[] strings = ParsingUtil.splitLineWithSpace(fileContent.get(i));
+            String result = strings[ParsingUtil.noParseInt(config.getRowNumber())];
+
+            fpValues.add(new BigDecimal(result));
+        }
+    }
+
+
+    private List<BigDecimal> parsingOpenCapacityValue(String sign, List<String> fileContent) {
+        List<BigDecimal> openCapacityValues = new ArrayList<>();
+        try {
+            if (sign.equals("") || sign == null) {
+                openCapacityValues = null;
+            } else {
+                parsingValues(sign, fileContent, openCapacityValues);
+                log.info("解析短期【开机容量】成功!!!==》记录数:{}", openCapacityValues.size());
+            }
         } catch (RuntimeException e) {
-            log.error("解析短期【预测数据】失败");
+            log.error("解析短期【开机容量】失败");
+            openCapacityValues = null;
             e.printStackTrace();
         } finally {
-            return fpValues;
+            return openCapacityValues;
         }
     }
 
+
     public List<ParsingDq> selectByStationCode(String stationCode) {
         return this.parsingDqs.stream().filter(p -> p.getStationCode().equals(stationCode)).collect(Collectors.toList());
     }

+ 2 - 2
cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingFjServiceImpl.java

@@ -132,9 +132,9 @@ public class ParsingFjServiceImpl extends ServiceImpl<ParsingFjMapper, ParsingFj
 
     @Override
     public boolean activationParsingConf() {
-        this.parsingFjs = baseMapper.selectList(null);
+        this.parsingFjs = list();
         this.windTurbineInfos = windTurbineInfoService.list();
-        return false;
+        return true;
     }
 
     @Override

+ 2 - 2
cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingNbqServiceImpl.java

@@ -134,9 +134,9 @@ public class ParsingNbqServiceImpl extends ServiceImpl<ParsingNbqMapper, Parsing
 
     @Override
     public boolean activationParsingConf() {
-        this.parsingNbqs = baseMapper.selectList(null);
+        this.parsingNbqs = list();
         this.inverterInfos = inverterInfoService.list();
-        return false;
+        return true;
     }
 
     @Override

+ 2 - 2
cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingNwpServiceImpl.java

@@ -161,8 +161,8 @@ public class ParsingNwpServiceImpl extends ServiceImpl<ParsingNwpMapper, Parsing
 
     @Override
     public boolean activationParsingConf() {
-        this.parsingNwps = baseMapper.selectList(null);
-        return false;
+        this.parsingNwps = list();
+        return true;
     }
 
     @Override

+ 2 - 2
cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingQxzServiceImpl.java

@@ -123,9 +123,9 @@ public class ParsingQxzServiceImpl extends ServiceImpl<ParsingQxzMapper, Parsing
 
     @Override
     public boolean activationParsingConf() {
-        this.parsingQxzs = baseMapper.selectList(null);
+        this.parsingQxzs = list();
         this.weatherStationInfos = weatherStationInfoService.list();
-        return false;
+        return true;
     }
 
     @Override

+ 217 - 0
cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingRcdqServiceImpl.java

@@ -0,0 +1,217 @@
+package com.cpp.web.service.datafactory.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cpp.web.domain.datafactory.BaseParsing;
+import com.cpp.web.domain.datafactory.ParsingCdq;
+import com.cpp.web.domain.datafactory.dto.ParsingConfParam;
+import com.cpp.web.domain.datafactory.dto.ParsingResultDto;
+import com.cpp.web.domain.datafactory.enums.FileTypeEnum;
+import com.cpp.web.domain.station.ForecastPowerUltraShortTermStation;
+import com.cpp.web.mapper.datafactory.ParsingCdqMapper;
+import com.cpp.web.service.datafactory.ParsingCdqService;
+import com.cpp.web.service.datafactory.ParsingInterface;
+import com.cpp.web.service.station.ForecastPowerUltraShortTermStationService;
+import com.cpp.web.utils.ParsingFieldUtil;
+import com.cpp.web.utils.ParsingFileUtil;
+import com.cpp.web.utils.ParsingUtil;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.File;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 超短期解析业务层实现类
+ *
+ * @author tl
+ * @date 2022-05-11 18:07:03
+ */
+@Service("rcdqParsing")
+@AllArgsConstructor
+@Slf4j
+@Transactional
+public class ParsingRcdqServiceImpl extends ServiceImpl<ParsingCdqMapper, ParsingCdq> implements ParsingCdqService, ParsingInterface {
+
+    private final ForecastPowerUltraShortTermStationService forecastPowerUltraShortTermStationService;
+
+    private List<ParsingCdq> parsingCdqs = new ArrayList<>();
+
+    @Override
+    public boolean save(BaseParsing parsingInfo) {
+        return true;
+    }
+
+    @Override
+    public boolean deleteById(Long id) {
+        return true;
+    }
+
+    @Override
+    public ParsingResultDto parsing(File file, String stationCode) {
+
+        ParsingResultDto parsingResultDto = new ParsingResultDto();
+        parsingResultDto.setFileName(file.getName());
+        parsingResultDto.setFileType(FileTypeEnum.cdq.name());
+
+        try {
+            List<ForecastPowerUltraShortTermStation> forecastPowerUltraShortTermStationList = new ArrayList();
+
+            List<ParsingCdq> parsingCdqList = selectByStationCode(stationCode);
+
+            if (!parsingCdqList.isEmpty()) {
+                ParsingCdq parsingCdq = parsingCdqList.get(0);
+
+                List<String> fileContent = ParsingFileUtil.getFileContent(file);
+                if (parsingCdq.getDataType().equals(ParsingFieldUtil.MULTI)) {//多行操作
+                    Date forecastTime = parsingForecastTime(parsingCdq.getForecastTime(), fileContent);
+                    Date time = forecastTime;
+                    if (forecastTime != null) {//解析时间成功才可以进行以下操作
+                        if (parsingCdq.getFpValue() != null) {
+                            List<BigDecimal> fpValues = parsingFpValue(parsingCdq.getFpValue(), fileContent);
+                            if (fpValues.size() > 0) {
+                                BigDecimal openCapacity = parsingValue(parsingCdq.getOpenCapacity(), fileContent);
+                                for (BigDecimal fpValue : fpValues) {
+                                    ForecastPowerUltraShortTermStation forecastPowerUltraShortTermStation = new ForecastPowerUltraShortTermStation();
+                                    forecastPowerUltraShortTermStation.setStationCode(stationCode);
+                                    forecastPowerUltraShortTermStation.setFpValue(fpValue);
+                                    forecastPowerUltraShortTermStation.setTime(time);
+                                    forecastPowerUltraShortTermStation.setForecastHowLongAgo(calcHowLongAgo(forecastTime, time));
+                                    forecastPowerUltraShortTermStation.setOpenCapacity(openCapacity);
+                                    forecastPowerUltraShortTermStationList.add(forecastPowerUltraShortTermStation);
+                                    time = new Date(time.getTime() + 900000L);//递增15分钟
+                                }
+                                forecastPowerUltraShortTermStationService.saveBatch(forecastPowerUltraShortTermStationList);
+                                log.info("解析 调控后CDQ文件:{} 成功! O(∩_∩)O", file.getName());
+                                parsingResultDto.setStatus("success");
+                            } else {
+                                parsingResultDto.setMessage("解析超短期文件时间错误");
+                                log.error("解析 调控后CDQ文件时间错误");
+                            }
+                        } else {
+                            parsingResultDto.setMessage("调控后超短期文件中时间无法解析");
+                            log.error("调控后cdq文件里日期不对");
+                        }
+
+                    } else {
+                        parsingResultDto.setMessage("解析 调控后超短期文件无数据");
+                        log.error("解析 调控后超短期文件无数据");
+                    }
+                } else {
+                    parsingResultDto.setMessage("调控后超短期暂无单行解析方式");
+                    log.error(" 调控后cdq暂无单行解析方式");
+                }
+            }
+
+        } catch (Exception e) {
+            parsingResultDto.setMessage("解析 调控后超短期数据失败!");
+            log.error("解析 调控后超短期数据失败! /(ㄒoㄒ)/~~", e);
+        } finally {
+            return parsingResultDto;
+        }
+    }
+
+    @Override
+    public boolean activationParsingConf() {
+        this.parsingCdqs = list();
+        return true;
+    }
+
+    //解析预测时间
+    protected Date parsingForecastTime(String sign, List<String> fileContent) {
+        Date forecastTime = null;
+        try {
+            ParsingConfParam config = ParsingFieldUtil.getConfig(sign);
+
+            String s = fileContent.get(ParsingUtil.noParseInt(config.getLineNumber()));
+            int signIndex = s.indexOf(config.getDataSign());
+            String result;
+            if (signIndex > 0) {
+                int startLength = config.getDataSign().length() + signIndex + 1;
+                int length = config.getFormat().length();
+                if (String.valueOf(s.charAt(startLength + 1)).equals("'")) {
+                    startLength += 1;
+                }
+                result = s.substring(startLength, startLength + length);
+
+                SimpleDateFormat simpleDateFormat = new SimpleDateFormat(config.getFormat());
+
+                forecastTime = simpleDateFormat.parse(result);
+
+                log.info("解析 调控后超短期【预测时间】成功,开始时间为:{}", result);
+            } else {
+                log.error("解析 调控后超短期【预测时间】时公式标识不存在所在行");
+            }
+
+        } catch (RuntimeException e) {
+            log.error("解析 调控后超短期【预测时间】失败");
+            e.printStackTrace();
+        } finally {
+            return forecastTime;
+        }
+
+    }
+
+
+    /*
+     * 解析配置格式规则:
+     *   s=>>1=>>entity=
+     *   s:单行标识
+     *   1:取值在1行
+     *   entity=:键标记标记
+     *
+     *   m=>>4-20=>>3
+     *   m:多行标识
+     *   4-20:取值在4-20行
+     *   3:第三列
+     * */
+    protected List<BigDecimal> parsingFpValue(String sign, List<String> fileContent) {
+        List<BigDecimal> fpValues = new ArrayList<>();
+        try {
+            ParsingConfParam config = ParsingFieldUtil.getConfig(sign);
+
+
+            String[] lineNumber = config.getLineNumber().split("-");
+            int startLine = ParsingUtil.noParseInt(lineNumber[0]);
+            int endLine = ParsingUtil.noParseInt(lineNumber[1]);
+
+            for (int i = startLine; i <= endLine; i++) {
+                String[] strings = ParsingUtil.splitLineWithSpace(fileContent.get(i));
+                String result = strings[ParsingUtil.noParseInt(config.getRowNumber())];
+
+                fpValues.add(new BigDecimal(result));
+            }
+
+            log.info("解析 调控后超短期【预测数据】成功!!!,记录数:{}", fpValues.size());
+
+        } catch (RuntimeException e) {
+            log.error("解析 调控后超短期【预测数据】失败");
+            e.printStackTrace();
+        } finally {
+            return fpValues;
+        }
+    }
+
+    /**
+     * 计算D+x中的x
+     *
+     * @param baseTime
+     * @param time
+     */
+    public Integer calcHowLongAgo(Date baseTime, Date time) {
+        return ((int) (time.getTime() - baseTime.getTime() % 900000L)) + 1;
+    }
+
+
+    public List<ParsingCdq> selectByStationCode(String stationCode) {
+        return this.parsingCdqs.stream().filter(p -> p.getStationCode().equals(stationCode)).collect(Collectors.toList());
+    }
+
+
+}

+ 242 - 0
cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingRdqServiceImpl.java

@@ -0,0 +1,242 @@
+package com.cpp.web.service.datafactory.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cpp.web.domain.datafactory.BaseParsing;
+import com.cpp.web.domain.datafactory.ParsingDq;
+import com.cpp.web.domain.datafactory.dto.ParsingConfParam;
+import com.cpp.web.domain.datafactory.dto.ParsingResultDto;
+import com.cpp.web.domain.datafactory.enums.FileTypeEnum;
+import com.cpp.web.domain.station.ForecastPowerShortTermRegulation;
+import com.cpp.web.mapper.datafactory.ParsingDqMapper;
+import com.cpp.web.service.datafactory.ParsingDqService;
+import com.cpp.web.service.datafactory.ParsingInterface;
+import com.cpp.web.service.station.ForecastPowerShortTermRegulationService;
+import com.cpp.web.utils.ParsingFieldUtil;
+import com.cpp.web.utils.ParsingFileUtil;
+import com.cpp.web.utils.ParsingUtil;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.File;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 调控后短期解析业务层实现类 开头r代表调控后
+ *
+ * @author tl
+ * @date 2022-05-11 18:07:03
+ */
+@Service("rdqParsing")
+@Slf4j
+@AllArgsConstructor
+@Transactional
+public class ParsingRdqServiceImpl extends ServiceImpl<ParsingDqMapper, ParsingDq> implements ParsingDqService, ParsingInterface {
+
+    private final ForecastPowerShortTermRegulationService forecastPowerShortTermRegulationService;
+
+    private List<ParsingDq> parsingDqs = new ArrayList<>();
+
+    @Override
+    public boolean save(BaseParsing parsing) {
+        return true;
+    }
+
+    @Override
+    public boolean deleteById(Long id) {
+        return true;
+    }
+
+    @Override
+    public boolean activationParsingConf() {
+        this.parsingDqs = list();
+        return true;
+    }
+
+    @Override
+    public ParsingResultDto parsing(File file, String stationCode) {
+        ParsingResultDto parsingResultDto = new ParsingResultDto();
+        parsingResultDto.setFileType(FileTypeEnum.dq.name());
+        parsingResultDto.setFileName(file.getName());
+
+        try {
+            List<ForecastPowerShortTermRegulation> forecastPowerShortTermRegulationList = new ArrayList();
+
+            List<ParsingDq> parsingDqList = selectByStationCode(stationCode);
+
+            if (!parsingDqList.isEmpty()) {
+                ParsingDq parsingDqInfo = parsingDqList.get(0);
+                List<String> fileContent = ParsingFileUtil.getFileContent(file);
+                if (parsingDqInfo.getDataType().equals(ParsingFieldUtil.MULTI)) {//多行操作
+                    Date forecastTime = parsingForecastTime(parsingDqInfo.getForecastTime(), fileContent);
+                    Date time = forecastTime;
+                    if (forecastTime != null) {//解析时间成功才可以进行以下操作
+                        if (parsingDqInfo.getFpValue() != null) {
+                            List<BigDecimal> fpValues = parsingFpValue(parsingDqInfo.getFpValue(), fileContent);
+                            if (fpValues.size() > 0) {
+                                BigDecimal capacity = parsingValue(parsingDqInfo.getCapacity(), fileContent);
+                                for (BigDecimal fpValue : fpValues) {
+                                    ForecastPowerShortTermRegulation forecastPowerShortTermRegulation = new ForecastPowerShortTermRegulation();
+                                    forecastPowerShortTermRegulation.setStationCode(stationCode);
+                                    forecastPowerShortTermRegulation.setFpValue(fpValue);
+                                    forecastPowerShortTermRegulation.setTime(time);
+                                    forecastPowerShortTermRegulation.setForecastHowLongAgo(calcHowLongAgo(forecastTime, time));
+                                    forecastPowerShortTermRegulation.setCapacity(capacity);
+                                    forecastPowerShortTermRegulationList.add(forecastPowerShortTermRegulation);
+                                    time = new Date(time.getTime() + 900000L);//递增15分钟
+                                }
+
+                                List<BigDecimal> openCapacityList = parsingOpenCapacityValue(parsingDqInfo.getOpenCapacity(), fileContent);
+                                if (openCapacityList != null && openCapacityList.size() == fpValues.size()) {
+                                    for (int i = 0; i < forecastPowerShortTermRegulationList.size(); i++) {
+                                        forecastPowerShortTermRegulationList.get(i).setOpenCapacity(openCapacityList.get(i));
+                                    }
+                                }
+
+                                forecastPowerShortTermRegulationService.saveBatch(forecastPowerShortTermRegulationList);
+                                log.info("解析 调控后DQ文件:{} 成功! O(∩_∩)O", file.getName());
+                                parsingResultDto.setStatus("success");
+                            } else {
+                                parsingResultDto.setMessage("解析 调控后短期文件时间错误");
+                                log.error("解析  调控后DQ文件时间错误");
+                            }
+                        } else {
+                            parsingResultDto.setMessage("调控后短期文件里日期不对");
+                            log.error("调控后dq文件里日期不对");
+                        }
+
+                    } else {
+                        parsingResultDto.setMessage("解析 调控后短期文件无数据");
+                        log.error("解析 调控后短期文件无数据");
+                    }
+
+
+                } else {
+                    parsingResultDto.setMessage("调控后短期暂无单行解析方式");
+                    log.info("调控后dq暂无单行解析方式");
+                }
+            }
+        } catch (Exception e) {
+            parsingResultDto.setMessage("解析 调控后短期数据失败!");
+            log.error("解析 调控后短期数据失败! /(ㄒoㄒ)/~~", e);
+        } finally {
+            return parsingResultDto;
+        }
+    }
+
+    protected Date parsingForecastTime(String sign, List<String> fileContent) {
+        Date forecastTime = null;
+        try {
+            ParsingConfParam config = ParsingFieldUtil.getConfig(sign);
+            String s = fileContent.get(ParsingUtil.noParseInt(config.getLineNumber()));
+            int signIndex = s.indexOf(config.getDataSign());
+            String result;
+            if (signIndex > 0) {
+                int startLength = config.getDataSign().length() + signIndex + 1;
+                int length = config.getFormat().length();
+                if (String.valueOf(s.charAt(startLength + 1)).equals("'")) {
+                    startLength += 1;
+                }
+                result = s.substring(startLength, startLength + length);
+
+                SimpleDateFormat simpleDateFormat = new SimpleDateFormat(config.getFormat());
+
+                forecastTime = simpleDateFormat.parse(result);
+
+                log.info("解析 调控后短期【预测时间】成功==》开始时间为:{}", result);
+            } else {
+                log.error("解析 调控后短期【预测时间】时公式标识不存在所在行");
+            }
+        } catch (RuntimeException e) {
+            log.error("解析 调控后短期【预测时间】失败");
+            e.printStackTrace();
+        } finally {
+            return forecastTime;
+        }
+
+    }
+
+
+    /*
+     * 解析配置格式规则:
+     *   s=>>1=>>entity=
+     *   s:单行标识
+     *   1:取值在1行
+     *   entity=:键标记标记
+     *
+     *   m=>>4-20=>>3
+     *   m:多行标识
+     *   4-20:取值在4-20行
+     *   3:第三列
+     * */
+    private List<BigDecimal> parsingFpValue(String sign, List<String> fileContent) {
+        List<BigDecimal> fpValues = new ArrayList<>();
+        try {
+            parsingValues(sign, fileContent, fpValues);
+
+            log.info("解析 调控后短期【预测数据】成功!!!==》记录数:{}", fpValues.size());
+        } catch (RuntimeException e) {
+            log.error("解析 调控后短期【预测数据】失败");
+            e.printStackTrace();
+        } finally {
+            return fpValues;
+        }
+    }
+
+    private void parsingValues(String sign, List<String> fileContent, List<BigDecimal> fpValues) {
+        ParsingConfParam config = ParsingFieldUtil.getConfig(sign);
+
+
+        String[] lineNumber = config.getLineNumber().split("-");
+        int startLine = ParsingUtil.noParseInt(lineNumber[0]);
+        int endLine = ParsingUtil.noParseInt(lineNumber[1]);
+
+        for (int i = startLine; i <= endLine; i++) {
+            String[] strings = ParsingUtil.splitLineWithSpace(fileContent.get(i));
+            String result = strings[ParsingUtil.noParseInt(config.getRowNumber())];
+
+            fpValues.add(new BigDecimal(result));
+        }
+    }
+
+
+    private List<BigDecimal> parsingOpenCapacityValue(String sign, List<String> fileContent) {
+        List<BigDecimal> openCapacityValues = new ArrayList<>();
+        try {
+            if (sign.equals("") || sign == null) {
+                openCapacityValues = null;
+            } else {
+                parsingValues(sign, fileContent, openCapacityValues);
+                log.info("解析 调控后短期【开机容量】成功!!!==》记录数:{}", openCapacityValues.size());
+            }
+        } catch (RuntimeException e) {
+            log.error("解析 调控后短期【开机容量】失败");
+            openCapacityValues = null;
+            e.printStackTrace();
+        } finally {
+            return openCapacityValues;
+        }
+    }
+
+
+    public List<ParsingDq> selectByStationCode(String stationCode) {
+        return this.parsingDqs.stream().filter(p -> p.getStationCode().equals(stationCode)).collect(Collectors.toList());
+    }
+
+
+    /**
+     * 计算D+x中的x
+     *
+     * @param baseTime
+     * @param time
+     */
+    public Integer calcHowLongAgo(Date baseTime, Date time) {
+        return ((int) (time.getTime() - baseTime.getTime() % 86400000L)) + 1;
+    }
+}

+ 14 - 19
cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingRpServiceImpl.java

@@ -1,6 +1,7 @@
 package com.cpp.web.service.datafactory.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cpp.web.domain.BaseCppEntity;
 import com.cpp.web.domain.datafactory.BaseParsing;
 import com.cpp.web.domain.datafactory.ParsingRp;
 import com.cpp.web.domain.datafactory.dto.ParsingConfParam;
@@ -25,6 +26,7 @@ import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * 实际功率解析业务层实现类
@@ -71,24 +73,17 @@ public class ParsingRpServiceImpl extends ServiceImpl<ParsingRpMapper, ParsingRp
 
                     if (time != null) {
 
-                        BigDecimal realValue = new BigDecimal(-99);
-                        if (parsingRpInfo.getRealValue() != null)
-                            realValue = parsingValue(parsingRpInfo.getRealValue(), fileContent);
-
-                        BigDecimal ableValue = new BigDecimal(-99);
-                        if (parsingRpInfo.getAbleValue() != null)
-                            ableValue = parsingValue(parsingRpInfo.getAbleValue(), fileContent);
-
-                        BigDecimal theoryValue = new BigDecimal(-99);
-                        if (parsingRpInfo.getTheoryValue() != null)
-                            theoryValue = parsingValue(parsingRpInfo.getTheoryValue(), fileContent);
-
-
                         PowerStationStatusData powerStationStatusData = new PowerStationStatusData();
                         powerStationStatusData.setStationCode(stationCode);
-                        powerStationStatusData.setTheoryValue(theoryValue);
-                        powerStationStatusData.setAbleValue(ableValue);
-                        powerStationStatusData.setRealValue(realValue);
+                        powerStationStatusData.setTheoryValue(parsingValue(parsingRpInfo.getTheoryValue(), fileContent));
+                        powerStationStatusData.setAbleValue(parsingValue(parsingRpInfo.getAbleValue(), fileContent));
+                        powerStationStatusData.setRealValue(parsingValue(parsingRpInfo.getRealValue(), fileContent));
+                        Integer powerRationing = parsingValue(parsingRpInfo.getRealValue(), fileContent).intValue();
+                        powerStationStatusData.setPowerRationing(powerRationing != 1 ? 0 : 1);
+                        powerStationStatusData.setOpenCapacity(parsingValue(parsingRpInfo.getOpenCapacity(), fileContent));
+                        powerStationStatusData.setCapacity(parsingValue(parsingRpInfo.getCapacity(), fileContent));
+                        powerStationStatusData.setBlockedCapacity(parsingValue(parsingRpInfo.getBlockedCapacity(), fileContent));
+
                         powerStationStatusData.setTime(time);
 
                         powerStationStatusDataService.save(powerStationStatusData);
@@ -115,12 +110,13 @@ public class ParsingRpServiceImpl extends ServiceImpl<ParsingRpMapper, ParsingRp
 
     @Override
     public boolean activationParsingConf() {
-        return false;
+        this.parsingRps = list();
+        return true;
     }
 
     @Override
     public List selectByStationCode(String stationCode) {
-        return null;
+        return this.parsingRps.stream().filter(p->p.getStationCode().equals(stationCode)).collect(Collectors.toList());
     }
 
 
@@ -157,5 +153,4 @@ public class ParsingRpServiceImpl extends ServiceImpl<ParsingRpMapper, ParsingRp
     }
 
 
-
 }

+ 136 - 0
cpp-admin/src/main/java/com/cpp/web/service/datafactory/impl/ParsingStatusServiceImpl.java

@@ -0,0 +1,136 @@
+package com.cpp.web.service.datafactory.impl;
+
+import cn.hutool.json.JSONUtil;
+import com.cpp.web.domain.AbnormalAlarm;
+import com.cpp.web.domain.datafactory.BaseParsing;
+import com.cpp.web.domain.datafactory.dto.ParsingResultDto;
+import com.cpp.web.domain.datafactory.enums.FileTypeEnum;
+import com.cpp.web.domain.enums.AlarmEnum;
+import com.cpp.web.domain.enums.DataSourcesEnum;
+import com.cpp.web.service.AbnormalAlarmService;
+import com.cpp.web.service.datafactory.ParsingInterface;
+import com.cpp.web.utils.MessageUtils;
+import com.cpp.web.utils.ParsingFileUtil;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.File;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 气象站解析业务层实现类
+ *
+ * @author tl
+ * @date 2022-05-11 18:07:03
+ */
+@Service("statusParsing")
+@Slf4j
+@AllArgsConstructor
+@Transactional
+public class ParsingStatusServiceImpl implements ParsingInterface {
+
+    private final AbnormalAlarmService abnormalAlarmService;
+
+    @Override
+    public boolean save(BaseParsing parsingInfo) {
+        return true;
+    }
+
+    @Override
+    public boolean deleteById(Long id) {
+        return true;
+    }
+
+
+    @Override
+    public ParsingResultDto parsing(File file, String stationCode) {
+
+        ParsingResultDto parsingResultDto = new ParsingResultDto();
+        parsingResultDto.setFileName(file.getName());
+        parsingResultDto.setFileType(FileTypeEnum.status.name());
+        try {
+
+            String json = ParsingFileUtil.getStr(file);
+            StationStatusDto stationStatusDto = JSONUtil.parse(json).toBean(StationStatusDto.class);
+            List<AbnormalAlarm> abnormalAlarms = stationStatusDto.generateAbnormalAlarm(stationCode);
+            if (abnormalAlarms.size() > 0) {
+                abnormalAlarmService.saveBatch(abnormalAlarms);
+            }
+
+            log.info("解析RP文件:{} 成功! O(∩_∩)O", file.getName());
+            parsingResultDto.setStatus("success");
+            parsingResultDto.setMessage("解析站端状态数据失败!");
+        } catch (Exception e) {
+            parsingResultDto.setMessage("解析站端状态数据失败!");
+            log.error("解析站端状态数据失败! /(ㄒoㄒ)/~~", e);
+        } finally {
+            return parsingResultDto;
+        }
+    }
+
+    @Override
+    public boolean activationParsingConf() {
+        return true;
+    }
+
+    @Override
+    public List selectByStationCode(String stationCode) {
+        return null;
+    }
+
+
+    @Data
+    class StationStatusDto {
+        private List<ChannelError> channelErrors;
+        private List<UploadFile> uploadFiles;
+        private BigDecimal hardDiskCapacity;
+
+
+        /**
+         * 生成告警
+         *
+         * @return
+         */
+        private List<AbnormalAlarm> generateAbnormalAlarm(String stationCode) {
+
+            List<AbnormalAlarm> list = new ArrayList<>();
+            if (this.channelErrors != null) {
+                for (ChannelError channelError : this.channelErrors) {
+                    list.add(new AbnormalAlarm(DataSourcesEnum.E1, AlarmEnum.E1, channelError.getMsg(), stationCode));
+                }
+            }
+
+
+            if (this.uploadFiles != null) {
+                for (UploadFile uploadFile : this.uploadFiles) {
+                    list.add(new AbnormalAlarm(DataSourcesEnum.E1, AlarmEnum.E2, MessageUtils.format("站端[{}]类型文件:【{}】未上报!", uploadFile.getType(), uploadFile.getName()), stationCode));
+                }
+            }
+
+            if (this.hardDiskCapacity != null) {
+                if (this.hardDiskCapacity.compareTo(new BigDecimal(95)) > -1) {
+                    list.add(new AbnormalAlarm(DataSourcesEnum.E1, AlarmEnum.E3, MessageUtils.format("站端磁盘空间达到 {}%,请关注!", this.hardDiskCapacity), stationCode));
+                }
+            }
+
+            return list;
+        }
+    }
+
+
+    @Data
+    class ChannelError {
+        private String msg;
+    }
+
+    @Data
+    class UploadFile {
+        private String type;
+        private String name;
+    }
+}

+ 21 - 0
cpp-admin/src/main/java/com/cpp/web/service/impl/AbnormalAlarmServiceImpl.java

@@ -0,0 +1,21 @@
+package com.cpp.web.service.impl;
+
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cpp.web.domain.AbnormalAlarm;
+import com.cpp.web.mapper.AbnormalAlarmMapper;
+import com.cpp.web.service.AbnormalAlarmService;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 告警信息层实现类
+ *
+ * @author tl
+ * @date 2022-05-11 18:07:03
+ */
+@AllArgsConstructor
+@Slf4j
+public class AbnormalAlarmServiceImpl extends ServiceImpl<AbnormalAlarmMapper, AbnormalAlarm> implements AbnormalAlarmService {
+
+}

+ 37 - 0
cpp-admin/src/main/java/com/cpp/web/service/station/ForecastPowerShortTermRegulationService.java

@@ -0,0 +1,37 @@
+package com.cpp.web.service.station;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cpp.web.domain.station.ForecastPowerShortTermRegulation;
+
+import java.util.List;
+
+/**
+ * cpp_forecast_power_short_term_his
+ *
+ * @author tl
+ * @date 2024-09-23 15:28:33
+ */
+public interface ForecastPowerShortTermRegulationService extends IService<ForecastPowerShortTermRegulation> {
+
+    /**
+     * 根据时间 提前多久预测 场站编号查询数据
+     *
+     * @param time        时间
+     * @param howLongAgo  提前多久预测
+     * @param stationCode 场站数据
+     * @return
+     */
+    ForecastPowerShortTermRegulation findByForecastTimeAndForecastHowLongAgoAndStationCode(Long time, int howLongAgo, String stationCode);
+
+    /**
+     * 根据时间 提前多久预测 场站编号查询数据
+     *
+     * @param startTime   开始时间
+     * @param endTime     结束时间
+     * @param howLongAgo  提前多久预测
+     * @param stationCode 场站编号
+     * @return
+     */
+    List<ForecastPowerShortTermRegulation> findByForecastTimeBetweenAndForecastHowLongAgoAndStationCode(Long startTime, Long endTime, Integer howLongAgo, String stationCode);
+
+}

+ 20 - 0
cpp-admin/src/main/java/com/cpp/web/service/station/ForecastPowerUltraShortTermRegulationService.java

@@ -0,0 +1,20 @@
+package com.cpp.web.service.station;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cpp.web.domain.station.ForecastPowerUltraShortTermRegulation;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * cpp_forecast_power_ultra_short_term_his
+ *
+ * @author tl
+ * @date 2024-09-23 15:28:33
+ */
+public interface ForecastPowerUltraShortTermRegulationService extends IService<ForecastPowerUltraShortTermRegulation> {
+
+    List<ForecastPowerUltraShortTermRegulation> findByForecastTimeBetweenAndForecastHowLongAgoAndStationCode(Long startTime, Long endTime, Integer howLongAgo, String stationCode);
+
+    List<ForecastPowerUltraShortTermRegulation> findByForecastTimeAndStationCode(Long finalTime, String stationCode);
+}

+ 49 - 0
cpp-admin/src/main/java/com/cpp/web/service/station/impl/ForecastPowerShortTermRegulationServiceImpl.java

@@ -0,0 +1,49 @@
+package com.cpp.web.service.station.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cpp.web.domain.station.ForecastPowerShortTermRegulation;
+import com.cpp.web.mapper.station.ForecastPowerShortTermRegulationMapper;
+import com.cpp.web.service.station.ForecastPowerShortTermRegulationService;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * cpp_forecast_power_short_term_his
+ *
+ * @author tl
+ * @date 2024-09-23 15:28:33
+ */
+@Service
+public class ForecastPowerShortTermRegulationServiceImpl extends ServiceImpl<ForecastPowerShortTermRegulationMapper, ForecastPowerShortTermRegulation> implements ForecastPowerShortTermRegulationService {
+
+    @Override
+    public List<ForecastPowerShortTermRegulation> findByForecastTimeBetweenAndForecastHowLongAgoAndStationCode(Long startTime, Long endTime, Integer howLongAgo, String stationCode) {
+        QueryWrapper<ForecastPowerShortTermRegulation> wrapper = new QueryWrapper<>();
+        if (stationCode != null && !stationCode.equals("")) {
+            wrapper.eq("station_code", stationCode);
+        }
+        if (startTime != null && endTime != null) {
+            wrapper.between("forecast_time", new Date(startTime), new Date(endTime));
+        }
+        wrapper.eq("forecast_how_long_ago", howLongAgo);
+        return baseMapper.selectList(wrapper);
+    }
+
+    @Override
+    public ForecastPowerShortTermRegulation findByForecastTimeAndForecastHowLongAgoAndStationCode(Long time, int howLongAgo, String stationCode) {
+        QueryWrapper<ForecastPowerShortTermRegulation> wrapper = new QueryWrapper<>();
+
+        if (stationCode != null && !stationCode.equals("")) {
+            wrapper.eq("station_code", stationCode);
+        }
+        if (time != null) {
+            wrapper.eq("forecast_time", new Date(time));
+        }
+        wrapper.eq("forecast_how_long_ago", howLongAgo);
+        return baseMapper.selectOne(wrapper);
+    }
+
+}

+ 51 - 0
cpp-admin/src/main/java/com/cpp/web/service/station/impl/ForecastPowerUltraShortTermRegulationServiceImpl.java

@@ -0,0 +1,51 @@
+package com.cpp.web.service.station.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cpp.web.domain.station.ForecastPowerUltraShortTermRegulation;
+import com.cpp.web.domain.station.ForecastPowerUltraShortTermStation;
+import com.cpp.web.mapper.station.ForecastPowerUltraShortTermRegulationMapper;
+import com.cpp.web.mapper.station.ForecastPowerUltraShortTermStationMapper;
+import com.cpp.web.service.station.ForecastPowerUltraShortTermRegulationService;
+import com.cpp.web.service.station.ForecastPowerUltraShortTermStationService;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * cpp_forecast_power_ultra_short_term_his
+ *
+ * @author tl
+ * @date 2024-09-23 15:28:33
+ */
+@Service
+public class ForecastPowerUltraShortTermRegulationServiceImpl extends ServiceImpl<ForecastPowerUltraShortTermRegulationMapper, ForecastPowerUltraShortTermRegulation> implements ForecastPowerUltraShortTermRegulationService {
+
+    @Override
+    public List<ForecastPowerUltraShortTermRegulation> findByForecastTimeBetweenAndForecastHowLongAgoAndStationCode(Long startTime, Long endTime, Integer howLongAgo, String stationCode) {
+        QueryWrapper<ForecastPowerUltraShortTermRegulation> wrapper = new QueryWrapper<>();
+
+        if (stationCode != null && !stationCode.equals("")) {
+            wrapper.eq("station_code", stationCode);
+        }
+        if (startTime != null && endTime != null) {
+            wrapper.between("forecast_time", new Date(startTime), new Date(endTime));
+        }
+        wrapper.eq("forecast_how_long_ago", howLongAgo);
+        return baseMapper.selectList(wrapper);
+    }
+
+    @Override
+    public List<ForecastPowerUltraShortTermRegulation> findByForecastTimeAndStationCode(Long finalTime, String stationCode) {
+        QueryWrapper<ForecastPowerUltraShortTermRegulation> wrapper = new QueryWrapper<>();
+
+        if (stationCode != null && !stationCode.equals("")) {
+            wrapper.eq("station_code", stationCode);
+        }
+        if (finalTime != null) {
+            wrapper.eq("forecast_time", new Date(finalTime));
+        }
+        return baseMapper.selectList(wrapper);
+    }
+}

+ 441 - 0
cpp-admin/src/main/java/com/cpp/web/utils/DateTimeUtil.java

@@ -0,0 +1,441 @@
+package com.cpp.web.utils;
+
+import com.cpp.common.utils.DateUtils;
+import com.sun.istack.NotNull;
+
+import java.math.BigDecimal;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 时间工具类
+ *
+ * @author zzy
+ * @version 1.0
+ * @since 2019/8/2 13:09
+ */
+@SuppressWarnings("WeakerAccess")
+public class DateTimeUtil {
+
+    /**
+     * 获取月份
+     *
+     * @param dateTime 时间,单位:毫秒
+     * @return 月份
+     */
+    public static int getMonth(@NotNull final Long dateTime) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTimeInMillis(dateTime);
+        return calendar.get(Calendar.MONTH) + 1;
+    }
+
+    /**
+     * 获取指定时间在当天所处于的时刻(15分钟为一个时刻)
+     * 例如:dateTime:2018-10-22 16:44:00
+     * 从0点0分开始计算,0点0分-0点15为第一个时刻,依次类推该时间的时刻数为67
+     *
+     * @param dateTime 时间,单位:毫秒
+     * @return 时刻
+     */
+    public static int getMomentFor15Minute(@NotNull final Long dateTime) {
+        return (int) ((dateTime - DateTimeUtil.getDayStartTime(dateTime).getTime()) / (15 * 60 * 1000)) + 1;
+    }
+
+    /**
+     * 获取指定时间在当天所处于的时刻(5分钟为一个时刻)
+     * 例如:dateTime:2018-10-22 01:44:00
+     * 从0点0分开始计算,0点0分-0点5为第一个时刻,依次类推该时间的时刻数为
+     *
+     * @param dateTime 时间,单位:毫秒
+     * @return 时刻
+     */
+    public static int getMomentFor5Minute(@NotNull final Long dateTime) {
+        return (int) ((dateTime - DateTimeUtil.getDayStartTime(dateTime).getTime()) / (5 * 60 * 1000)) + 1;
+    }
+
+
+    /**
+     * 获取指定时间在当天所处于的时刻(1分钟为一个时刻)
+     *
+     * @param dateTime 时间,单位:毫秒
+     * @return 时刻
+     */
+    public static int getMomentForMinute(@NotNull final Long dateTime) {
+        return (int) ((dateTime - DateTimeUtil.getDayStartTime(dateTime).getTime()) / (1 * 60 * 1000)) + 1;
+    }
+
+    /**
+     * 获取指定时间所在时刻的标记时间(15分钟为一个时刻)<br>
+     * 例如:dateTime:2018-10-22 16:44:00 <br>
+     * 标记时间为2018-10-22 16:30:00
+     *
+     * @param dateTime 时间,单位:毫秒
+     */
+    public static Date getMomentTimeFor15Minute(@NotNull final Long dateTime) {
+        int moment = DateTimeUtil.getMomentFor15Minute(dateTime);// 获取指定时间所在时刻数
+        long differentTime = moment * 15 * 60 * 1000;// 获取从0分0秒开始到现在的时间间隔,单位:毫秒
+        long dayStartTime = DateTimeUtil.getDayStartTime(dateTime).getTime();
+        return new Date(dayStartTime + differentTime - 15 * 60 * 1000);
+    }
+
+    /**
+     * 获取指定时间所在时刻的标记时间(5分钟为一个时刻)<br>
+     * 例如:dateTime:2018-10-22 16:44:00 <br>
+     * 标记时间为2018-10-22 16:40:00
+     *
+     * @param dateTime 时间,单位:毫秒
+     * @return 指定时间所在时刻的标记时间,单位:毫秒
+     */
+    public static Date getMomentTimeFor5Minute(@NotNull final Long dateTime) {
+        int moment = DateTimeUtil.getMomentFor5Minute(dateTime);// 获取指定时间所在时刻数
+        long differentTime = moment * 5 * 60 * 1000;// 获取从0分0秒开始到现在的时间间隔,单位:毫秒
+        long dayStartTime = DateTimeUtil.getDayStartTime(dateTime).getTime();
+        return new Date(dayStartTime + differentTime - 5 * 60 * 1000);
+    }
+
+    /**
+     * 获取当前时间(时间粒度分钟)
+     *
+     * @return 当前时间
+     */
+    public static Date getCurrentTimeForMinute() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        return calendar.getTime();
+    }
+
+    /**
+     * 获取指定时间所在天的0点0分
+     *
+     * @param dateTime 时间毫秒
+     * @return 0点0分的毫秒
+     */
+    public static Date getDayStartTime(@NotNull final Long dateTime) {
+        Calendar date = Calendar.getInstance();
+        date.setTimeInMillis(dateTime);
+        date.set(Calendar.HOUR_OF_DAY, 0);
+        date.set(Calendar.MINUTE, 0);
+        date.set(Calendar.SECOND, 0);
+        date.set(Calendar.MILLISECOND, 0);
+        return date.getTime();
+    }
+
+    /**
+     * 今日凌晨 毫秒
+     *
+     * @return 时间
+     */
+    public static long getMillisecondsSubDay() {
+
+        Calendar c = Calendar.getInstance();
+
+        return c.getTimeInMillis() - DateUtils.getFragmentInMilliseconds(c, Calendar.DAY_OF_MONTH);
+    }
+
+    /**
+     * 获取指定时间所在天的23点59分59秒
+     *
+     * @param dateTime 时间毫秒
+     * @return 23点59分59秒的毫秒
+     */
+    public static Date getDayLastTime(@NotNull final Long dateTime) {
+        Calendar date = Calendar.getInstance();
+        date.setTimeInMillis(dateTime);
+        date.set(Calendar.HOUR_OF_DAY, 23);
+        date.set(Calendar.MINUTE, 59);
+        date.set(Calendar.SECOND, 59);
+        date.set(Calendar.MILLISECOND, 999);
+        return date.getTime();
+    }
+
+    /**
+     * 获取两个时间间的间隔天数(自然天)
+     *
+     * @param dateFrom 开始时间
+     * @param dateTo   结束时间
+     * @return 自然天数
+     */
+    public static int getDaysBetweenTwoDate(Long dateFrom, Long dateTo) {
+        return (int) ((DateTimeUtil.getDayStartTime(dateTo).getTime() - DateTimeUtil.getDayStartTime(dateFrom).getTime()) / (1000 * 60 * 60 * 24L));
+    }
+
+    /**
+     * 获取两个时间间的间隔间隔时刻数(15分钟一个时刻)
+     *
+     * @param dateFrom 开始时间
+     * @param dateTo   结束时间
+     * @return 间隔时刻数
+     */
+    public static int getMomentsBetweenTwoDate(Long dateFrom, Long dateTo) {
+        return (int) ((dateTo - dateFrom) / (15 * 60 * 1000));
+    }
+
+
+    /**
+     * 获取现在时间
+     *
+     * @return 返回字符串格式 yyyy-MM-dd HH:mm:ss
+     */
+    public static String getStringDate() {
+        Date currentTime = new Date();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String dateString = formatter.format(currentTime);
+        return dateString;
+    }
+
+    /**
+     * 将长时间格式时间转换为字符串 yyyy-MM-dd HH:mm:ss
+     *
+     * @param dateDate
+     * @return
+     */
+    public static String dateToStrLong(Date dateDate) {
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String dateString = formatter.format(dateDate);
+        return dateString;
+    }
+
+    /**
+     * 将时间格式字符串转换为时间 HH:mm
+     *
+     * @param strDate
+     * @return
+     */
+    public static Date strToDateLongHM(String strDate) {
+        SimpleDateFormat formatter = new SimpleDateFormat("HH:mm");
+        ParsePosition pos = new ParsePosition(0);
+        Date strtodate = formatter.parse(strDate, pos);
+        return strtodate;
+    }
+
+    /**
+     * 判断tunnel日落
+     *
+     * @param time
+     * @param dfLonIn
+     * @param dfLatIn
+     * @return boolean 返回true,说明时间在日升日落之间,返回false,说明时间在日升之前或者日落之后。
+     */
+//    public static boolean checkInSunriseAndSunset(Long time, double dfLonIn, double dfLatIn) {
+//        Date date = new Date(time);
+//
+//        String str1 = SunRiseSet.getSunrise(new BigDecimal(dfLonIn), new BigDecimal(dfLatIn), date);
+//        String str2 = SunRiseSet.getSunset(new BigDecimal(dfLonIn), new BigDecimal(dfLatIn), date);
+//
+//        Date dt1 = null;
+//        Date dt2 = null;
+//        Date dt3 = null;
+//        try {
+//            dt1 = strToDateLongHM(dateToStrLong(date).substring(11, 16));
+//            dt2 = strToDateLongHM(str1);
+//            dt3 = strToDateLongHM(str2);
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+//        if (dt1.getTime() > dt2.getTime() && dt1.getTime() < dt3.getTime()) {
+//            return true;
+//        } else {
+//            return false;
+//        }
+//    }
+
+
+    /**
+     * 获取日升日落
+     *
+     * @param time
+     * @param dfLonIn
+     * @param dfLatIn
+     * @return boolean 返回true,说明时间在日升日落之间,返回false,说明时间在日升之前或者日落之后。
+     */
+//    public static List<Date> getSunriseAndSunset(Long time, double dfLonIn, double dfLatIn) {
+//        Date date = new Date(time);
+//
+//        String str1 = SunRiseSet.getSunrise(new BigDecimal(dfLonIn), new BigDecimal(dfLatIn), date);
+//        String str2 = SunRiseSet.getSunset(new BigDecimal(dfLonIn), new BigDecimal(dfLatIn), date);
+//
+//
+//        List<Date> dates = new ArrayList<>();
+//        dates.add(strToDateLongHM(str1));
+//        dates.add(strToDateLongHM(str2));
+//
+//        return dates;
+//    }
+
+    /**
+     * 判断时间是不是今天
+     *
+     * @param date
+     * @return 是返回true,不是返回false
+     */
+    public static boolean isNow(Date date) {
+        //当前时间
+        Date now = new Date();
+        SimpleDateFormat sf = new SimpleDateFormat("yyyyMMdd");
+        //获取今天的日期
+        String nowDay = sf.format(now);
+        //对比的时间
+        String day = sf.format(date);
+        return day.equals(nowDay);
+    }
+
+    /**
+     * 取最近的整点,0-30取前面的整点,31-59取后面的整点
+     *
+     * @param timestamp
+     * @return 返回整点时间戳
+     */
+    public static Long nwpAddStartMinutes(Long timestamp) {
+        // 创建 Calendar 对象
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTimeInMillis(timestamp);
+
+        // 获取分钟数
+        int minutes = calendar.get(Calendar.MINUTE);
+
+        // 如果分钟数大于等于31,向后一个小时取整点
+        if (minutes >= 31) {
+            calendar.add(Calendar.HOUR_OF_DAY, 1);
+            calendar.set(Calendar.MINUTE, 0);
+        } else {
+            // 如果分钟数在00和30之间,取当前小时的整点
+            calendar.set(Calendar.MINUTE, 0);
+        }
+
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+
+        // 返回毫秒级时间戳
+        return calendar.getTimeInMillis();
+    }
+
+
+    /**
+     * 根据调用开始的方法返回的时间往后加5个小时
+     *
+     * @param time
+     * @return 返回当前时间加5个小时时间戳
+     */
+    public static Long nwpAddEndMinutes(Long time) {
+        // 将最近整点的时间戳转换为Instant对象
+        Instant startInstant = Instant.ofEpochMilli(time);
+
+        // 将以毫秒为单位的时间间隔转换为秒
+        long secondsToAdd = 4 * 60 * 60 + 45 * 60; // 4小时45分钟
+
+        // 往后推4小时45分钟
+        Instant newInstant = startInstant.plusMillis(secondsToAdd * 1000);
+
+        return newInstant.toEpochMilli();
+    }
+
+    /**
+     * 根据当前所处不同时间,返回对应的分钟时间戳
+     * 46至00传45末尾的env,01至15传00末尾的env,16至30传15末尾的env,31至45传30末尾的env
+     *
+     * @param timestamp
+     * @return 返回当前时间加5个小时时间戳
+     */
+    public static Long windMinusEndMinutes(Long timestamp) {
+        // 创建 Calendar 对象
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTimeInMillis(timestamp);
+
+        // 获取小时和分钟数
+        int hours = calendar.get(Calendar.HOUR_OF_DAY);
+        int minutes = calendar.get(Calendar.MINUTE);
+
+        // 根据规定逻辑修改分钟数
+        if (minutes >= 1 && minutes <= 15) {
+            minutes = 0;
+        } else if (minutes <= 30) {
+            minutes = 15;
+        } else if (minutes <= 45) {
+            minutes = 30;
+        } else {
+            minutes = 45;
+        }
+
+        // 设置修改后的小时和分钟数
+        calendar.set(Calendar.HOUR_OF_DAY, hours);
+        calendar.set(Calendar.MINUTE, minutes);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+
+        // 返回毫秒级时间戳
+        return calendar.getTimeInMillis();
+    }
+
+    /**
+     * 根据传入时间往前推两个小时
+     *
+     * @param timestamp
+     * @return 返回env开始时间戳
+     */
+    public static long windMinusStartMinutes(long timestamp) {
+        // 将毫秒级时间戳转换为Instant对象
+        Instant instant = Instant.ofEpochMilli(timestamp);
+
+        // 往前推2小时
+        Instant newInstant = instant.minusSeconds((1 * 60 + 45) * 60);
+
+        // 将毫秒部分设为0
+        LocalDateTime localDateTime = LocalDateTime.ofInstant(newInstant, ZoneOffset.UTC);
+        localDateTime = localDateTime.withSecond(0).withNano(0);
+
+        // 转换为Instant对象
+        Instant updatedInstant = localDateTime.toInstant(ZoneOffset.UTC);
+
+        return updatedInstant.toEpochMilli();
+    }
+
+    /**
+     * 传入系统时间,判断当前时刻,调用不同的HistoryRp
+     * 举例: 在46至00传45末尾的his(后5分钟最后一个点替换00末尾,并调用55时刻的历史功率值)
+     *
+     * @param sysTime
+     * @return 返回0就用老方法,返回时间戳就用那个时刻的值作为历史功率值
+     */
+    public static long methodCategory(long sysTime) {
+        long time = 0;
+        long minuteTime = sysTime / (60 * 1000);
+        int currentMinute = (int) (minuteTime % 60);
+
+        long hourTime = sysTime / (3600 * 1000);
+
+        if (currentMinute >= 11 && currentMinute <= 15) {
+            time = hourTime * 3600000L + 10 * 60000L;
+        } else if (currentMinute >= 26 && currentMinute <= 30) {
+            time = hourTime * 3600000L + 25 * 60000L;
+        } else if (currentMinute >= 41 && currentMinute <= 45) {
+            time = hourTime * 3600000L + 40 * 60000L;
+        } else if (currentMinute >= 56 || currentMinute == 0) {
+            time = hourTime * 3600000L + 55 * 60000L;
+        }
+
+        return time;
+    }
+
+
+    /**
+     * 获取指定时间在当天所处于第多少个
+     * 例如:dateTime:2018-10-22 01:44:00
+     * 从0点0分开始计算,0点0分-0点5为第一个时刻,依次类推该时间的时刻数为
+     *
+     * @param dateTime 时间,单位:毫秒
+     * @param interval
+     * @return 时刻
+     */
+    public static int getMomentForInterval(@NotNull final Long dateTime, Integer interval) {
+        return (int) ((dateTime - DateTimeUtil.getDayStartTime(dateTime).getTime()) / (interval)) + 1;
+    }
+
+}

+ 46 - 0
cpp-admin/src/main/java/com/cpp/web/utils/MessageUtils.java

@@ -0,0 +1,46 @@
+package com.cpp.web.utils;
+
+import java.math.BigDecimal;
+
+/**
+ * 信息拼装工具类
+ *
+ * @Author: tl
+ * @Date: 2023/8/1 15:30
+ */
+public class MessageUtils {
+
+
+  public static String normal(String methodName) {
+    return methodName + "【结果正常】";
+
+  }
+
+  public static String abnormal(String methodName) {
+    return methodName + "×结果异常×";
+  }
+
+  public static String insufficient(String methodName) {
+    return methodName + "【所需数据不足,暂不进行此项校验】";
+  }
+
+  public static String success(String methodName, BigDecimal value) {
+    return methodName + "【尝试修复成功,结果为: {" + value + "}】";
+  }
+
+  public static String fail(String methodName) {
+    return methodName + "×尝试修复失败×";
+  }
+
+
+
+
+
+  public static String format(String message, Object... args) {
+    for (Object arg : args) {
+      message = message.replaceFirst("\\{\\}", arg.toString());
+    }
+    return message;
+  }
+
+}

+ 141 - 0
cpp-admin/src/main/java/com/cpp/web/utils/NumberUtils.java

@@ -0,0 +1,141 @@
+package com.cpp.web.utils;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.math.BigDecimal;
+
+/**
+ * 提供高精度的运算支持
+ *
+ * @author bizy
+ * @version 2.0
+ */
+@Slf4j
+public class NumberUtils {
+    private NumberUtils() {
+    }
+
+    /**
+     * 精确的加法运算.
+     *
+     * @param b1    加数
+     * @param b2    加数
+     * @param scale 运算结果小数后精确的位数
+     * @return 结果
+     */
+    public static BigDecimal add(BigDecimal b1, BigDecimal b2, int scale) {
+        return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP);
+    }
+
+    /**
+     * 精确的加法运算.
+     *
+     * @param b1 加数
+     * @param b2 加数
+     * @return 保留2位小数
+     */
+    public static BigDecimal add(BigDecimal b1, BigDecimal b2) {
+        return b1.add(b2).setScale(2, BigDecimal.ROUND_HALF_UP);
+    }
+
+    /**
+     * 精确的减法运算.
+     *
+     * @param b1    被减数
+     * @param b2    减数
+     * @param scale 运算结果小数后精确的位数
+     * @return 结果
+     */
+    public static BigDecimal subtract(BigDecimal b1, BigDecimal b2, int scale) {
+        return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP);
+    }
+
+
+    /**
+     * 精确的减法运算.
+     *
+     * @param b1 被减数
+     * @param b2 减数
+     * @return 结果 保留2位小数
+     */
+    public static BigDecimal subtract(BigDecimal b1, BigDecimal b2) {
+        return b1.subtract(b2).setScale(2, BigDecimal.ROUND_HALF_UP);
+    }
+
+    /**
+     * 提供精确的乘法运算,并对运算结果截位.
+     *
+     * @param b1    乘数
+     * @param b2    乘数
+     * @param scale 运算结果小数后精确的位数
+     * @return 结果
+     */
+    public static BigDecimal multiply(BigDecimal b1, BigDecimal b2, int scale) {
+        if (scale < 0) {
+            throw new IllegalArgumentException("The scale must be a positive integer or zero");
+        }
+        return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP);
+    }
+
+    /**
+     * 提供精确的乘法运算,并对运算结果截位.
+     *
+     * @param b1 乘数
+     * @param b2 乘数
+     * @return 结果 保留2位小数
+     */
+    public static BigDecimal multiply(BigDecimal b1, BigDecimal b2) {
+        return b1.multiply(b2).setScale(2, BigDecimal.ROUND_HALF_UP);
+    }
+
+
+    /**
+     * 提供(相对)精确的除法运算. 由scale参数指定精度,以后的数字四舍五入.
+     *
+     * @param b1    被除数
+     * @param b2    除数
+     * @param scale 表示表示需要精确到小数点以后几位
+     * @return 结果
+     */
+    public static BigDecimal divide(BigDecimal b1, BigDecimal b2, int scale) {
+        if (scale < 0) {
+            throw new IllegalArgumentException("The scale must be a positive integer or zero");
+        }
+        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP);
+    }
+
+    /**
+     * 提供(相对)精确的除法运算. 由scale参数指定精度,以后的数字四舍五入.
+     *
+     * @param b1 被除数
+     * @param b2 除数
+     * @return 结果 保留2位小数
+     */
+    public static BigDecimal divide(BigDecimal b1, BigDecimal b2) {
+        return b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP);
+    }
+
+    /**
+     * 提供精确的小数位四舍五入处理.
+     *
+     * @param b     需要四舍五入的数字
+     * @param scale 小数点后保留几位
+     * @return TODO
+     */
+    public static BigDecimal round(BigDecimal b, int scale) {
+        if (scale < 0) {
+            throw new IllegalArgumentException("The scale must be a positive integer or zero");
+        }
+        return b.setScale(scale, BigDecimal.ROUND_HALF_UP);
+    }
+
+    /**
+     * 提供精确的小数位四舍五入处理.
+     *
+     * @param b 需要四舍五入的数字
+     * @return 保留2位小数
+     */
+    public static BigDecimal round(BigDecimal b) {
+        return b.setScale(2, BigDecimal.ROUND_HALF_UP);
+    }
+}