xushili преди 1 година
родител
ревизия
5f3a42519f

+ 42 - 12
power-fitting-JN/src/main/java/com.gyee.power.fitting/dispersionanalysis/InverterAnalysis2.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.gyee.power.fitting.common.feign.RemoteServiceBuilder;
 import com.gyee.power.fitting.common.result.JsonResult;
 import com.gyee.power.fitting.common.result.ResultCode;
+import com.gyee.power.fitting.model.PhotovoltaicAnalysis;
 import com.gyee.power.fitting.model.ProBasicEquipment;
 import com.gyee.power.fitting.model.ProBasicEquipmentPoint;
 import com.gyee.power.fitting.model.ProEconEquipmentmodel;
@@ -13,7 +14,9 @@ import com.gyee.power.fitting.service.ProBasicEquipmentPointService;
 import com.gyee.power.fitting.service.ProBasicEquipmentService;
 import com.gyee.power.fitting.service.ProEconEquipmentmodelService;
 import org.apache.commons.lang3.StringUtils;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 
 import javax.annotation.Resource;
 import java.util.ArrayList;
@@ -23,9 +26,10 @@ import java.util.Map;
 import java.util.stream.Collectors;
 
 //等效发电时分析
-@CrossOrigin
-@RequestMapping("/equivalent")
-@RestController
+//@CrossOrigin
+//@RequestMapping("/equivalent")
+//@RestController
+@Component
 public class InverterAnalysis2 {
 
     @Resource
@@ -37,8 +41,10 @@ public class InverterAnalysis2 {
     @Resource
     private RemoteServiceBuilder remoteService;
 
-    // 计算等效发电时的标准差
-    private static double calculateStandardDeviationEquivalentOperatingHours(Map<String, Double> data, double average) {
+    /**
+     * 计算等效发电时的标准差
+     */
+    public double calcStandardDeviationEquivalentOperatingHours(Map<String, Double> data, double average) {
         double sum = 0.0;
         for (double value : data.values()) {
             sum += Math.pow(value - average, 2);
@@ -46,6 +52,17 @@ public class InverterAnalysis2 {
         return Math.sqrt(sum / data.size());
     }
 
+    /**
+     * 计算等效发电时的标准差
+     */
+    public double calcStdDevEquivOperatHours(List<PhotovoltaicAnalysis> datas, double average) {
+        double sum = 0.0;
+        for (PhotovoltaicAnalysis value : datas) {
+            sum += Math.pow(value.getEquivalentGeneratingTime() - average, 2);
+        }
+        return Math.sqrt(sum / datas.size());
+    }
+
     @GetMapping("/powertime")
     private JSONObject getFileList(
             @RequestParam(value = "station", required = true) String station,
@@ -93,7 +110,7 @@ public class InverterAnalysis2 {
             if (endData == null || startData == null || ims == null) {
                 dxfds = 0;
             } else {
-                dxfds = calculateEquivalentOperatingHours(endData.getDoubleValue() - startData.getDoubleValue(), emMap.get(ims));
+                dxfds = calcEquivalentOperatingHours(endData.getDoubleValue() - startData.getDoubleValue(), emMap.get(ims));
             }
             dxfdsSum += dxfds;
             dxfdsData.put(s, dxfds);
@@ -106,7 +123,7 @@ public class InverterAnalysis2 {
         double average = dxfdsSum / inverterIds.size();
 
         // 计算等效发电时的标准差
-        double stdDeviation = calculateStandardDeviationEquivalentOperatingHours(dxfdsData, average);
+        double stdDeviation = calcStandardDeviationEquivalentOperatingHours(dxfdsData, average);
 
         // 存储极差逆变单元的列表
         List<String> outlierInverters = new ArrayList<>();
@@ -122,14 +139,27 @@ public class InverterAnalysis2 {
         return JsonResult.successData(ResultCode.SUCCESS, inverterData2s);
     }
 
-    // 计算等效发电时
-    private double calculateEquivalentOperatingHours(double power, double installedCapacity) {
+    /**
+     * 计算等效发电时
+     *
+     * @param power             一段时间内的发电量
+     * @param installedCapacity 逆变器的装机容量
+     * @return
+     */
+    public double calcEquivalentOperatingHours(double power, double installedCapacity) {
         if (installedCapacity == 0) return 0;
         return power / installedCapacity;
     }
 
-    // 根据等效发电时、平均值和标准差确定运行水平
-    private String determineOperatingLevel(double equivalentOperatingHours, double average, double stdDeviation) {
+    /**
+     * 根据等效发电时、平均值和标准差确定运行水平
+     *
+     * @param equivalentOperatingHours 等效发电时
+     * @param average                  平均值
+     * @param stdDeviation             标准差
+     * @return
+     */
+    public String determineOperatingLevel(double equivalentOperatingHours, double average, double stdDeviation) {
         double deviation = equivalentOperatingHours - average;
 
         // 使用标准差的倍数来判断运行水平

+ 0 - 3
power-fitting-JN/src/main/java/com.gyee.power.fitting/dispersionanalysis/InverterPowerAnalysis.java

@@ -1,12 +1,9 @@
 package com.gyee.power.fitting.dispersionanalysis;
 
-import org.springframework.stereotype.Service;
-
 import java.io.FileWriter;
 import java.io.IOException;
 import java.util.*;
 
-@Service
 public class InverterPowerAnalysis {
 
     public static void main(String[] args) {

+ 31 - 46
power-fitting-JN/src/main/java/com.gyee.power.fitting/dispersionanalysis/InverterPowerAnalysis2.java

@@ -7,21 +7,21 @@ import com.gyee.power.fitting.common.result.ResultCode;
 import com.gyee.power.fitting.model.custom.PhotovoltaicInfo;
 import com.gyee.power.fitting.service.impl.IvPvCurveFittingService;
 import org.apache.commons.math3.fitting.WeightedObservedPoints;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 
 import javax.annotation.Resource;
-import java.io.FileWriter;
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-import java.util.Random;
 import java.util.stream.Collectors;
 
 //逆变器单位装机输出功率离散率分析
-@CrossOrigin
-@RequestMapping("/discreteness")
-@RestController
+//@CrossOrigin
+//@RequestMapping("/discreteness")
+//@RestController
+@Component
 public class InverterPowerAnalysis2 {
 
     @Resource
@@ -29,22 +29,8 @@ public class InverterPowerAnalysis2 {
     @Resource
     private PolynomialCurveFitting pncf;
 
-    // 模拟生成逆变器数据
-    private static List<InverterData> generateInverterData() {
-        List<InverterData> data = new ArrayList<>();
-        Random rand = new Random();
-        for (int i = 1; i <= 10; i++) {
-            String inverterId = "Inverter" + i;
-            long timestamp = System.currentTimeMillis();
-            double outputPower = rand.nextDouble() * 1000;
-            double lightIntensity = rand.nextDouble() * 1000;
-            data.add(new InverterData(inverterId, timestamp, outputPower, lightIntensity));
-        }
-        return data;
-    }
-
     // 计算平均功率
-    private static double calculateAveragePower(List<Double> powerData) {
+    public double calculateAveragePower(List<Double> powerData) {
         double sum = 0.0;
         for (Double power : powerData) {
             sum += power;
@@ -53,7 +39,7 @@ public class InverterPowerAnalysis2 {
     }
 
     // 根据复杂规则分析逆变器状态
-    private static String analyzeInverterStatus(double powerDeviation, double averagePower) {
+    public String analyzeInverterStatus(double powerDeviation, double averagePower) {
         if (powerDeviation < 0.1 && averagePower > 800) {
             return "运行稳定";
         } else if (powerDeviation < 0.2 && averagePower > 600) {
@@ -65,28 +51,6 @@ public class InverterPowerAnalysis2 {
         }
     }
 
-    // 将数据存储到CSV文件
-    private static void saveDataToCSV(Map<String, List<Double>> historicalPowerData, String fileName) {
-        try {
-            FileWriter writer = new FileWriter(fileName);
-            writer.append("InverterId,PowerData\n");
-            for (Map.Entry<String, List<Double>> entry : historicalPowerData.entrySet()) {
-                String inverterId = entry.getKey();
-                List<Double> powerData = entry.getValue();
-                StringBuilder powerDataStr = new StringBuilder();
-                for (Double power : powerData) {
-                    powerDataStr.append(power).append(",");
-                }
-                writer.append(inverterId).append(",").append(powerDataStr.toString()).append("\n");
-            }
-            writer.flush();
-            writer.close();
-            System.out.println("数据已保存到 " + fileName);
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-
     @GetMapping("/rate")
     private JSONObject getFileList(
             @RequestParam(value = "station", required = true) String station,
@@ -129,7 +93,7 @@ public class InverterPowerAnalysis2 {
     }
 
     // 分析逆变器性能,包括计算离散率和平均功率
-    private InverterData2 analyzeInverterPerformance(List<PhotovoltaicInfo> infos, double[] run, String inverterId) {
+    public InverterData2 analyzeInverterPerformance(List<PhotovoltaicInfo> infos, double[] run, String inverterId) {
 
         List<Double> collect = infos.stream().map(info -> info.getS()).collect(Collectors.toList());
         // 计算功率离散率
@@ -152,4 +116,25 @@ public class InverterPowerAnalysis2 {
         }
         return Math.sqrt(sum / powerData.size());
     }
+
+    // 计算功率离散率
+    public double calcPowerDeviation(List<PhotovoltaicInfo> infos, double averagePower) {
+        WeightedObservedPoints points = new WeightedObservedPoints();
+        for (PhotovoltaicInfo info : infos) {
+            if (info.getS() < 1) {
+                points.add(0, 0);
+            }
+            points.add(info.getS(), info.getActualP());
+        }
+
+        double[] run = pncf.run(points);
+
+        double sum = 0.0, power;
+        // 计算标准差
+        for (PhotovoltaicInfo info : infos) {
+            power = info.getActualP();
+            sum += Math.pow(power - pncf.calcPoly(power, run), 2);
+        }
+        return Math.sqrt(sum / infos.size());
+    }
 }

+ 202 - 0
power-fitting-JN/src/main/java/com.gyee.power.fitting/dispersionanalysis/PhotovoltaicAnalysisTask.java

@@ -0,0 +1,202 @@
+package com.gyee.power.fitting.dispersionanalysis;
+
+import cn.hutool.core.date.DateField;
+import cn.hutool.core.date.DateRange;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.gyee.power.fitting.common.feign.RemoteServiceBuilder;
+import com.gyee.power.fitting.model.PhotovoltaicAnalysis;
+import com.gyee.power.fitting.model.ProBasicEquipment;
+import com.gyee.power.fitting.model.ProBasicEquipmentPoint;
+import com.gyee.power.fitting.model.ProEconEquipmentmodel;
+import com.gyee.power.fitting.model.custom.PhotovoltaicInfo;
+import com.gyee.power.fitting.model.custom.TsDoubleData;
+import com.gyee.power.fitting.service.IPhotovoltaicAnalysisService;
+import com.gyee.power.fitting.service.ProBasicEquipmentPointService;
+import com.gyee.power.fitting.service.ProBasicEquipmentService;
+import com.gyee.power.fitting.service.ProEconEquipmentmodelService;
+import com.gyee.power.fitting.service.impl.IvPvCurveFittingService;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+
+@Component
+public class PhotovoltaicAnalysisTask {
+
+    @Resource
+    private ProBasicEquipmentService proBasicEquipmentService;
+    @Resource
+    private ProEconEquipmentmodelService proEconEquipmentmodelService;
+    @Resource
+    private ProBasicEquipmentPointService proBasicEquipmentPointService;
+    @Resource
+    private IPhotovoltaicAnalysisService photovoltaicAnalysisService;
+    @Resource
+    private RemoteServiceBuilder remoteService;
+    @Resource
+    private InverterAnalysis2 inverterAnalysis;
+    @Resource
+    private InverterPowerAnalysis2 inverterPowerAnalysis;
+    @Resource
+    private IvPvCurveFittingService curveFittingService;
+    @Resource
+    private PhotovoltaicEfficiencyAnalysis2 photovoltaicEfficiencyAnalysis;
+
+    //秒 分 时 日 月 周
+    @Scheduled(cron = "0 0 1 * * ?")
+    public void doTask() {
+        //获取逆变器
+        QueryWrapper<ProBasicEquipment> eWrapper = new QueryWrapper<>();
+        eWrapper.eq("spare1", "IN");
+        List<ProBasicEquipment> eList = proBasicEquipmentService.list(eWrapper);
+        //场站、机型、逆变器们
+        Map<String, Map<String, List<ProBasicEquipment>>> equipmentMapMap = eList.stream().collect(Collectors.groupingBy(
+                ProBasicEquipment::getWindpowerstationId, Collectors.groupingBy(ProBasicEquipment::getModelId)));
+
+        //获取机型的装机容量
+        List<ProEconEquipmentmodel> emList = proEconEquipmentmodelService.list();
+        //机型、装机容量
+        Map<String, Double> emMap = emList.stream().collect(Collectors.toMap(ProEconEquipmentmodel::getNemCode, ProEconEquipmentmodel::getPowerProduction));
+
+        //获取日发电量测点
+        QueryWrapper<ProBasicEquipmentPoint> rfdlWrapper = new QueryWrapper<>();
+        rfdlWrapper.eq("uniform_code", "RFDL").like("windturbine_id", "_IN_");
+        List<ProBasicEquipmentPoint> rfdlList = proBasicEquipmentPointService.list(rfdlWrapper);
+        String rfdlPoints = rfdlList.stream().map(ProBasicEquipmentPoint::getNemCode).collect(Collectors.joining(","));
+        //逆变器id,日发电量测点
+        Map<String, String> rfdlPointMap = rfdlList.stream().collect(Collectors.toMap(ProBasicEquipmentPoint::getWindturbineId, ProBasicEquipmentPoint::getNemCode));
+
+        //获取设备状态测点
+        QueryWrapper<ProBasicEquipmentPoint> sbztWrapper = new QueryWrapper<>();
+        sbztWrapper.eq("uniform_code", "SBZT").like("windturbine_id", "_IN_");
+        List<ProBasicEquipmentPoint> sbztList = proBasicEquipmentPointService.list(sbztWrapper);
+        //逆变器id,设备状态测点
+        Map<String, String> sbztPointMap = sbztList.stream().collect(Collectors.toMap(ProBasicEquipmentPoint::getWindturbineId, ProBasicEquipmentPoint::getNemCode));
+
+        //获取光伏分析表最后计算日期
+        QueryWrapper<PhotovoltaicAnalysis> paWrapper = new QueryWrapper<>();
+        paWrapper.select("max(data_date) data_date");
+        PhotovoltaicAnalysis paList = photovoltaicAnalysisService.getOne(paWrapper);
+        DateRange dateRange = getDateRange(paList.getDataDate());
+        if (dateRange == null) return;
+        for (DateTime dateTime : dateRange) {
+            DateTime endTime = dateTime.offsetNew(DateField.DAY_OF_YEAR, 1);
+            //测点、日发电量
+            Map<String, TsDoubleData> rfdlMap = remoteService.adaptergf().getHistorySection(rfdlPoints, endTime.getTime());
+
+            List<PhotovoltaicAnalysis> photovoltaicAnalyses = new ArrayList<>();
+            equipmentMapMap.forEach((stationId, vv) -> {
+                //逆变器,功率数据
+                Map<String, List<PhotovoltaicInfo>> datas2File1 = curveFittingService.getDatas2File1(stationId, dateTime.getTime(), endTime.getTime(), null);
+                //标准点
+                List<PhotovoltaicInfo> bzdList = curveFittingService.standardPointCalculate1(datas2File1);
+                //计算理论功率
+                Map<String, List<PhotovoltaicInfo>> llglInfos = curveFittingService.calculatAnalysis1(bzdList, datas2File1);
+
+                vv.forEach((modelId, equipments) -> {
+                    List<PhotovoltaicAnalysis> analysises = new ArrayList<>();
+                    //等效发电时之和
+                    AtomicReference<Double> hoursSum = new AtomicReference<>((double) 0);
+                    equipments.forEach(equipment -> {
+                        String equipmentId = equipment.getId();
+                        //逆变器日发电量测点
+                        String point = rfdlPointMap.get(equipmentId);
+
+                        PhotovoltaicAnalysis analysis = new PhotovoltaicAnalysis();
+                        analysis.setStationId(stationId);
+                        analysis.setProjectId(equipment.getProjectId());
+                        analysis.setLineId(equipment.getLineId());
+                        analysis.setEquipmentId(equipmentId);
+                        analysis.setDataDate(dateTime.toJdkDate());
+
+                        //设备状态
+                        List<TsDoubleData> sbztInfoList = remoteService.adaptergf().getRawValuesByKey(sbztPointMap.get(equipmentId), dateTime.getTime(), endTime.getTime());
+                        //计算故障导致停机时间
+                        double gzdztjSj = calcDowntimeByFailure(sbztInfoList);
+                        analysis.setMalfunctionTime(gzdztjSj);
+                        analysis.setDeviceAvailability((24 - gzdztjSj) / 24);
+
+                        //日发电量
+                        double rfdl = rfdlMap.get(point).getDoubleValue();
+                        analysis.setGeneratingAmount(rfdl);
+                        //等效发电时
+                        double dxfds = inverterAnalysis.calcEquivalentOperatingHours(rfdl, emMap.get(equipment.getModelId()));
+                        analysis.setEquivalentGeneratingTime(dxfds);
+
+                        //离散率计算
+                        List<PhotovoltaicInfo> lslList = datas2File1.get(equipmentId);
+                        //平均功率
+                        double pjGl = lslList.stream().filter(i -> i.getActualP() > 1).mapToDouble(PhotovoltaicInfo::getActualP).average().orElse(0);
+                        analysis.setAveragePower(pjGl);
+                        //平均理论功率
+                        double pjLlgl = llglInfos.get(equipmentId).stream().filter(i -> i.getActualP() > 1).mapToDouble(PhotovoltaicInfo::getIdeaP).average().orElse(0);
+                        analysis.setAverageTheoryPower(pjLlgl);
+                        //光伏转换效率
+                        double zhxl = photovoltaicEfficiencyAnalysis.calculatePhotovoltaicEfficiency(pjGl, pjLlgl);
+                        analysis.setConversionEfficiency(zhxl);
+                        String zhxlZt = photovoltaicEfficiencyAnalysis.determinePhotovoltaicLevel(zhxl);
+                        analysis.setConversionEfficiencyStatus(zhxlZt);
+                        //离散率
+                        double lsl = inverterPowerAnalysis.calcPowerDeviation(lslList, pjGl);
+                        analysis.setScatter(lsl);
+                        String lslZt = inverterPowerAnalysis.analyzeInverterStatus(lsl, pjGl);
+                        analysis.setScatterStatus(lslZt);
+
+                        hoursSum.updateAndGet(v -> v + dxfds);
+                        analysises.add(analysis);
+                    });
+                    List<PhotovoltaicAnalysis> analysisList = analysises.stream().peek(pa -> {
+                        //平均等效发电时
+                        double pjDxfds = hoursSum.get() / analysises.size();
+                        pa.setAverageEquivalentGeneratingT(pjDxfds);
+                        //等效发电时标准差
+                        double dxfdsBzc = inverterAnalysis.calcStdDevEquivOperatHours(analysises, pjDxfds);
+                        pa.setEquivalentGeneratingTimeStan(dxfdsBzc);
+                        //等效发电时状态
+                        String dxfdsZt = inverterAnalysis.determineOperatingLevel(pa.getEquivalentGeneratingTime(), pjDxfds, dxfdsBzc);
+                        pa.setEquivalentGeneratingTimeStat(dxfdsZt);
+                    }).collect(Collectors.toList());
+                    photovoltaicAnalyses.addAll(analysisList);
+                });
+            });
+            photovoltaicAnalysisService.saveBatch(photovoltaicAnalyses);
+        }
+    }
+
+    private double calcDowntimeByFailure(List<TsDoubleData> sbztInfoList) {
+        sbztInfoList = sbztInfoList.stream().sorted(Comparator.comparing(TsDoubleData::getTs).reversed()).collect(Collectors.toList());
+
+        long duration = 0;//故障或检修时间
+        long faultTime = sbztInfoList.get(0).getTs();
+        //测点列表
+        for (TsDoubleData tsPointData : sbztInfoList) {
+            //点值
+            int doubleValue = (int) tsPointData.getDoubleValue();
+            if (doubleValue == 2 || doubleValue == 3) {
+                duration += faultTime - tsPointData.getTs();
+                faultTime = tsPointData.getTs();
+            } else {
+                faultTime = tsPointData.getTs();
+            }
+        }
+        return duration / (1000.0 * 60 * 60);
+    }
+
+    private DateRange getDateRange(Date date) {
+        //paList.setDataDate(DateUtil.parse("2023-10-14"));
+        DateTime startTime;
+        DateTime endTime = DateUtil.beginOfDay(DateUtil.yesterday());
+        if (date == null) {
+            startTime = endTime;
+        } else {
+            startTime = DateUtil.offsetDay(date, 1);
+            if (startTime.isAfter(endTime)) return null;
+        }
+        return DateUtil.range(startTime, endTime, DateField.DAY_OF_YEAR);
+    }
+}

+ 13 - 10
power-fitting-JN/src/main/java/com.gyee.power.fitting/dispersionanalysis/PhotovoltaicEfficiencyAnalysis2.java

@@ -6,7 +6,9 @@ import com.gyee.power.fitting.common.result.ResultCode;
 import com.gyee.power.fitting.model.custom.PhotovoltaicInfo;
 import com.gyee.power.fitting.service.impl.IvPvCurveFittingService;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 
 import javax.annotation.Resource;
 import java.util.ArrayList;
@@ -15,16 +17,17 @@ import java.util.Map;
 
 //光伏转换效率分析
 @Slf4j
-@CrossOrigin
-@RequestMapping("/conversion")
-@RestController
+//@CrossOrigin
+//@RequestMapping("/conversion")
+//@RestController
+@Component
 public class PhotovoltaicEfficiencyAnalysis2 {
 
     @Resource
     private IvPvCurveFittingService curveFittingService;
 
     // 计算光伏转换效率
-    private static double calculatePhotovoltaicEfficiency(double actualOutputPower, double incidentSolarPower) {
+    public double calculatePhotovoltaicEfficiency(double actualOutputPower, double incidentSolarPower) {
         double v = (actualOutputPower / incidentSolarPower) * 100.0;
         if (v > 95) v = 95.0;
         // 转换为百分比
@@ -47,10 +50,10 @@ public class PhotovoltaicEfficiencyAnalysis2 {
         List<InverterData2> inverterData2s = new ArrayList<>();
         // 分析光伏逆变单元的运行水平
         datasInfos.forEach((k, v) -> {
-            double actualOutputPower = v.stream().mapToDouble(PhotovoltaicInfo::getActualP).sum();
-            double incidentSolarPower = v.stream().mapToDouble(PhotovoltaicInfo::getIdeaP).sum();
-            double sPower = v.stream().mapToDouble(PhotovoltaicInfo::getS).sum();
-            log.info(k + "逆变器转换率2:" + actualOutputPower / sPower);
+            double actualOutputPower = v.stream().mapToDouble(PhotovoltaicInfo::getActualP).average().orElse(0);
+            double incidentSolarPower = v.stream().mapToDouble(PhotovoltaicInfo::getIdeaP).average().orElse(actualOutputPower + 1);
+            //double sPower = v.stream().mapToDouble(PhotovoltaicInfo::getS).sum();
+            //log.info(k + "逆变器转换率2:" + actualOutputPower / sPower);
 
             double efficiency = calculatePhotovoltaicEfficiency(actualOutputPower, incidentSolarPower);
             String currentLevel = determinePhotovoltaicLevel(efficiency);
@@ -61,7 +64,7 @@ public class PhotovoltaicEfficiencyAnalysis2 {
     }
 
     // 根据转换效率确定光伏运行水平
-    private String determinePhotovoltaicLevel(double efficiency) {
+    public String determinePhotovoltaicLevel(double efficiency) {
         if (efficiency >= 90.0) {
             return "运行稳定";
         } else if (efficiency >= 80.0) {

+ 16 - 0
power-fitting-JN/src/main/java/com.gyee.power.fitting/mapper/PhotovoltaicAnalysisMapper.java

@@ -0,0 +1,16 @@
+package com.gyee.power.fitting.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.gyee.power.fitting.model.PhotovoltaicAnalysis;
+
+/**
+ * <p>
+ * 光伏分析 Mapper 接口
+ * </p>
+ *
+ * @author gfhd
+ * @since 2023-10-13
+ */
+public interface PhotovoltaicAnalysisMapper extends BaseMapper<PhotovoltaicAnalysis> {
+
+}

+ 291 - 0
power-fitting-JN/src/main/java/com.gyee.power.fitting/model/PhotovoltaicAnalysis.java

@@ -0,0 +1,291 @@
+package com.gyee.power.fitting.model;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * <p>
+ * 光伏分析
+ * </p>
+ *
+ * @author gfhd
+ * @since 2023-10-13
+ */
+@TableName("photovoltaic_analysis")
+public class PhotovoltaicAnalysis implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 场站
+     */
+    private String stationId;
+
+    /**
+     * 期次
+     */
+    private String projectId;
+
+    /**
+     * 线路
+     */
+    private String lineId;
+
+    /**
+     * 设备id
+     */
+    private String equipmentId;
+
+    /**
+     * 数据日期
+     */
+    private Date dataDate;
+
+    /**
+     * 平均功率
+     */
+    private Double averagePower;
+
+    /**
+     * 离散率
+     */
+    private Double scatter;
+
+    /**
+     * 离散率状态
+     */
+    private String scatterStatus;
+
+    /**
+     * 发电量
+     */
+    private Double generatingAmount;
+
+    /**
+     * 等效发电时
+     */
+    private Double equivalentGeneratingTime;
+
+    /**
+     * 平均等效发电时
+     */
+    private Double averageEquivalentGeneratingT;
+
+    /**
+     * 等效发电时标准差
+     */
+    private Double equivalentGeneratingTimeStan;
+
+    /**
+     * 等效发电时状态
+     */
+    private String equivalentGeneratingTimeStat;
+
+    /**
+     * 平均理论功率
+     */
+    private Double averageTheoryPower;
+
+    /**
+     * 平均理论功率
+     */
+    private Double conversionEfficiency;
+
+    /**
+     * 转换效率状态
+     */
+    private String conversionEfficiencyStatus;
+
+    /**
+     * 故障停机时间
+     */
+    private Double malfunctionTime;
+
+    /**
+     * 设备可利用率
+     */
+    private Double deviceAvailability;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public Double getConversionEfficiency() {
+        return conversionEfficiency;
+    }
+
+    public void setConversionEfficiency(Double conversionEfficiency) {
+        this.conversionEfficiency = conversionEfficiency;
+    }
+
+    public String getStationId() {
+        return stationId;
+    }
+
+    public void setStationId(String stationId) {
+        this.stationId = stationId;
+    }
+
+    public String getProjectId() {
+        return projectId;
+    }
+
+    public void setProjectId(String projectId) {
+        this.projectId = projectId;
+    }
+
+    public String getLineId() {
+        return lineId;
+    }
+
+    public void setLineId(String lineId) {
+        this.lineId = lineId;
+    }
+
+    public String getEquipmentId() {
+        return equipmentId;
+    }
+
+    public void setEquipmentId(String equipmentId) {
+        this.equipmentId = equipmentId;
+    }
+
+    public Date getDataDate() {
+        return dataDate;
+    }
+
+    public void setDataDate(Date dataDate) {
+        this.dataDate = dataDate;
+    }
+
+    public Double getAveragePower() {
+        return averagePower;
+    }
+
+    public void setAveragePower(Double averagePower) {
+        this.averagePower = averagePower;
+    }
+
+    public Double getScatter() {
+        return scatter;
+    }
+
+    public void setScatter(Double scatter) {
+        this.scatter = scatter;
+    }
+
+    public String getScatterStatus() {
+        return scatterStatus;
+    }
+
+    public void setScatterStatus(String scatterStatus) {
+        this.scatterStatus = scatterStatus;
+    }
+
+    public Double getGeneratingAmount() {
+        return generatingAmount;
+    }
+
+    public void setGeneratingAmount(Double generatingAmount) {
+        this.generatingAmount = generatingAmount;
+    }
+
+    public Double getEquivalentGeneratingTime() {
+        return equivalentGeneratingTime;
+    }
+
+    public void setEquivalentGeneratingTime(Double equivalentGeneratingTime) {
+        this.equivalentGeneratingTime = equivalentGeneratingTime;
+    }
+
+    public Double getAverageEquivalentGeneratingT() {
+        return averageEquivalentGeneratingT;
+    }
+
+    public void setAverageEquivalentGeneratingT(Double averageEquivalentGeneratingT) {
+        this.averageEquivalentGeneratingT = averageEquivalentGeneratingT;
+    }
+
+    public Double getEquivalentGeneratingTimeStan() {
+        return equivalentGeneratingTimeStan;
+    }
+
+    public void setEquivalentGeneratingTimeStan(Double equivalentGeneratingTimeStan) {
+        this.equivalentGeneratingTimeStan = equivalentGeneratingTimeStan;
+    }
+
+    public String getEquivalentGeneratingTimeStat() {
+        return equivalentGeneratingTimeStat;
+    }
+
+    public void setEquivalentGeneratingTimeStat(String equivalentGeneratingTimeStat) {
+        this.equivalentGeneratingTimeStat = equivalentGeneratingTimeStat;
+    }
+
+    public Double getAverageTheoryPower() {
+        return averageTheoryPower;
+    }
+
+    public void setAverageTheoryPower(Double averageTheoryPower) {
+        this.averageTheoryPower = averageTheoryPower;
+    }
+
+    public String getConversionEfficiencyStatus() {
+        return conversionEfficiencyStatus;
+    }
+
+    public void setConversionEfficiencyStatus(String conversionEfficiencyStatus) {
+        this.conversionEfficiencyStatus = conversionEfficiencyStatus;
+    }
+
+    public Double getMalfunctionTime() {
+        return malfunctionTime;
+    }
+
+    public void setMalfunctionTime(Double malfunctionTime) {
+        this.malfunctionTime = malfunctionTime;
+    }
+
+    public Double getDeviceAvailability() {
+        return deviceAvailability;
+    }
+
+    public void setDeviceAvailability(Double deviceAvailability) {
+        this.deviceAvailability = deviceAvailability;
+    }
+
+    @Override
+    public String toString() {
+        return "PhotovoltaicAnalysis{" +
+                "id = " + id +
+                ", stationId = " + stationId +
+                ", projectId = " + projectId +
+                ", lineId = " + lineId +
+                ", equipmentId = " + equipmentId +
+                ", dataDate = " + dataDate +
+                ", averagePower = " + averagePower +
+                ", scatter = " + scatter +
+                ", scatterStatus = " + scatterStatus +
+                ", generatingAmount = " + generatingAmount +
+                ", equivalentGeneratingTime = " + equivalentGeneratingTime +
+                ", averageEquivalentGeneratingT = " + averageEquivalentGeneratingT +
+                ", equivalentGeneratingTimeStan = " + equivalentGeneratingTimeStan +
+                ", equivalentGeneratingTimeStat = " + equivalentGeneratingTimeStat +
+                ", averageTheoryPower = " + averageTheoryPower +
+                ", conversionEfficiencyStatus = " + conversionEfficiencyStatus +
+                ", malfunctionTime = " + malfunctionTime +
+                ", deviceAvailability = " + deviceAvailability +
+                "}";
+    }
+}

+ 16 - 0
power-fitting-JN/src/main/java/com.gyee.power.fitting/service/IPhotovoltaicAnalysisService.java

@@ -0,0 +1,16 @@
+package com.gyee.power.fitting.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.gyee.power.fitting.model.PhotovoltaicAnalysis;
+
+/**
+ * <p>
+ * 光伏分析 服务类
+ * </p>
+ *
+ * @author gfhd
+ * @since 2023-10-13
+ */
+public interface IPhotovoltaicAnalysisService extends IService<PhotovoltaicAnalysis> {
+
+}

+ 764 - 0
power-fitting-JN/src/main/java/com.gyee.power.fitting/service/impl/IvPvCurveFittingService2.java

@@ -0,0 +1,764 @@
+package com.gyee.power.fitting.service.impl;
+
+import com.gyee.power.fitting.common.alg.CurrentVoltageCalc;
+import com.gyee.power.fitting.common.alg.PolynomialCurveFitting;
+import com.gyee.power.fitting.common.config.GyeeConfig;
+import com.gyee.power.fitting.common.constants.Constants;
+import com.gyee.power.fitting.common.feign.IAdapterService;
+import com.gyee.power.fitting.common.feign.RemoteServiceBuilder;
+import com.gyee.power.fitting.common.spring.InitialRunner;
+import com.gyee.power.fitting.common.util.DateUtils;
+import com.gyee.power.fitting.common.util.FileUtil;
+import com.gyee.power.fitting.common.util.PowerFittingUtil;
+import com.gyee.power.fitting.model.*;
+import com.gyee.power.fitting.model.anno.AnnotationTool;
+import com.gyee.power.fitting.model.anno.FixedVo;
+import com.gyee.power.fitting.model.custom.FjjxbVo;
+import com.gyee.power.fitting.model.custom.PhotovoltaicInfo;
+import com.gyee.power.fitting.model.custom.TableTitle;
+import com.gyee.power.fitting.model.custom.TsDoubleData;
+import com.gyee.power.fitting.service.IWindpowerstationtestingpoint2Service;
+import com.gyee.power.fitting.service.ProBasicEquipmentPointService;
+import com.gyee.power.fitting.service.ProBasicPowerstationPointService;
+import com.gyee.power.fitting.service.Windturbinetestingpointai2Service;
+import com.gyee.power.fitting.service.custom.curve.DataScangfService;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.math3.fitting.WeightedObservedPoints;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@Service
+public class IvPvCurveFittingService2 {
+
+    @Resource
+    private IWindpowerstationtestingpoint2Service windpowerstationtestingpoint2Service;
+    @Resource
+    private Windturbinetestingpointai2Service windturbinetestingpointai2Service;
+
+    @Resource
+    private ProBasicWeatherStationServiceImpl weatherStationService;
+
+    @Resource
+    private ProBasicEquipmentPointService proBasicEquipmentPointService;
+
+    @Resource
+    private ProBasicPowerstationPointService proBasicPowerstationPointService;
+    @Resource
+    private IAdapterService adpClient;
+
+    @Autowired
+    private RemoteServiceBuilder remoteService;
+
+    @Resource
+    private GyeeConfig config;
+    @Resource
+    private PolynomialCurveFitting pncf;
+
+    private List<FixedVo> fixedVos;
+    private Map<String, String> uniforcodes;
+
+    @Resource
+    private DataScangfService dataScangfService;
+
+    public void getDatas2File(String stationid, long start, long end, int interval) {
+
+        int daym = 24 * 60 * 60 * 1000;
+
+        //按天
+        for (long i = start; i < end; i += daym) {
+
+            List<List<PhotovoltaicInfo>> datas = getDatas(stationid, i, i + daym, interval);
+            infos2File(datas);
+        }
+    }
+
+    public Map<String, List<PhotovoltaicInfo>> getDatas2File1(String stationid, long start, long end, Integer interval) {
+
+        int daym = 24 * 60 * 60 * 1000;
+        Map<String, List<PhotovoltaicInfo>> wj = new HashMap<>();
+        //按天
+        for (long i = start; i < end; i += daym) {
+
+            List<List<PhotovoltaicInfo>> datas = getDatas(stationid, i, i + daym, interval);
+            for (List<PhotovoltaicInfo> data : datas) {
+                List<PhotovoltaicInfo> infos = wj.get(data.get(0).getInverter());
+                if (infos == null) {
+                    wj.put(data.get(0).getInverter(), data);
+                } else {
+                    infos.addAll(data);
+                }
+            }
+        }
+        return wj;
+    }
+
+    private void infos2File(List<List<PhotovoltaicInfo>> datas) {
+
+        //文件第一行
+        List<FixedVo> fixedVos = AnnotationTool.getFixedVoList(PhotovoltaicInfo.class);
+        String columnName = fixedVos.stream().map(FixedVo::getDes).collect(Collectors.joining(","));
+        //遍历逆变器
+        for (List<PhotovoltaicInfo> data : datas) {
+            PhotovoltaicInfo info = data.get(0);
+            String station = info.getStation();
+            String fileName = config.getFilePathPrepare() + "gf" + File.separator + "一秒" + File.separator + station + "-" + info.getInverter() + "-" + DateUtils.date2StringS(new Date(info.getTime())) + ".csv";
+            File file = new File(fileName);
+            if (file.exists()) continue;
+            StringBuilder sb = new StringBuilder();
+            sb.append(columnName).append("\n");
+            for (PhotovoltaicInfo datum : data) {
+                sb.append(datum.getStation()).append(",").append(datum.getInverter()).append(",").append(DateUtils.date2StringL(new Date(datum.getTime())))
+                        .append(",").append(datum.getT()).append(",").append(datum.getS()).append(",").append(datum.getI()).append(",").append(datum.getV())
+                        .append(",").append(datum.getActualP()).append(",").append(datum.getAI()).append(",").append(datum.getAV()).append(",")
+                        .append(datum.getBI()).append(",").append(datum.getBV()).append(",").append(datum.getCI()).append(",").append(datum.getCV())
+                        .append("\n");
+            }
+            FileUtil.writeFile(fileName, sb.toString());
+        }
+    }
+
+    public List<String> getFileList(String station, List<String> nbq, long startdate, int interval, long enddate, boolean isOffline) {
+        List<String> fileList = new ArrayList<>();
+        File file = null;
+        //获取文件位置
+        if (interval == 1) {
+            file = new File(config.getFilePathPrepare() + "gf" + File.separator + "一秒" + File.separator);
+        } else if (interval == 1) {
+            file = new File(config.getFilePathPrepare() + "gf" + File.separator + "一秒" + File.separator);
+        }
+        //获取文件列表
+        File[] files = file.listFiles();
+        //如果文件不够,返回null
+        for (long i = startdate; i < enddate; i += 24 * 60 * 60 * 1000) {
+            int size = fileList.size();
+            String s = DateUtils.date2StringS(new Date(i));
+            for (File f : files) {
+                if (f.getName().contains(station) && f.getName().contains(s) && jiancha(f.getName(), nbq))
+                    fileList.add(f.getName());
+            }
+            if (fileList.size() == size && !isOffline) return null;
+        }
+        return fileList;
+    }
+
+    private boolean jiancha(String name, List<String> nbq) {
+        for (String s : nbq) {
+            if (name.contains(s)) return true;
+        }
+        return false;
+    }
+
+    public Map<String, Object> getTable(String s) {
+        List<FixedVo> fixedVos = AnnotationTool.getFixedVoList(PhotovoltaicInfo.class);
+        List<TableTitle> collect = fixedVos.stream().map(d -> new TableTitle(d.getName(), d.getDes())).collect(Collectors.toList());
+        Map<String, Object> tableMap = new HashMap<>();
+        String fs = config.getFilePathPrepare() + "gf" + File.separator + s;
+        List<PhotovoltaicInfo> infos = file2Info(fs, false);
+        tableMap.put("data", infos);
+        tableMap.put("title", collect);
+        return tableMap;
+    }
+
+    private List<PhotovoltaicInfo> file2Info(String path, boolean isAll) {
+        List<String> strings = FileUtil.readFile(path, isAll);
+        List<PhotovoltaicInfo> infos = new ArrayList<>();
+        for (int i = 1; i < strings.size(); i++) {
+            String[] split = strings.get(i).split(",");
+            PhotovoltaicInfo info = new PhotovoltaicInfo();
+            try {
+                info.setStation(split[0]);
+                info.setInverter(split[1]);
+                if (!"".equals(split[2])) {
+                    info.setTime(DateUtils.string2DateL(split[2]).getTime());
+                    info.setDatetime(split[2]);
+                }
+                info.setT(StringUtils.isBlank(split[3]) ? 0 : Double.parseDouble(split[3]));
+                info.setS(StringUtils.isBlank(split[4]) ? 0 : Double.parseDouble(split[4]));
+                info.setI(StringUtils.isBlank(split[5]) ? 0 : Double.parseDouble(split[5]));
+                info.setV(StringUtils.isBlank(split[6]) ? 0 : Double.parseDouble(split[6]));
+                info.setActualP(StringUtils.isBlank(split[7]) ? 0 : Double.parseDouble(split[7]));
+                info.setAI(StringUtils.isBlank(split[8]) ? 0 : Double.parseDouble(split[8]));
+                info.setAV(StringUtils.isBlank(split[9]) ? 0 : Double.parseDouble(split[9]));
+                info.setBI(StringUtils.isBlank(split[10]) ? 0 : Double.parseDouble(split[10]));
+                info.setBV(StringUtils.isBlank(split[11]) ? 0 : Double.parseDouble(split[11]));
+                info.setCI(StringUtils.isBlank(split[12]) ? 0 : Double.parseDouble(split[12]));
+                info.setCV(StringUtils.isBlank(split[13]) ? 0 : Double.parseDouble(split[13]));
+            } catch (Exception e) {
+                System.out.println();
+            }
+
+            infos.add(info);
+        }
+        return infos;
+    }
+
+    /**
+     * 计算理论功率加入原列表
+     *
+     * @return
+     */
+    public Map<String, List<PhotovoltaicInfo>> calculatAnalysis(List<String> fileList) {
+
+        String bzcldPath = config.getFilePathPrepare() + "bzd" + File.separator + "标准点.csv";
+        List<PhotovoltaicInfo> bzclds = file2Info(bzcldPath, true);
+        Map<String, PhotovoltaicInfo> bzcldMap = bzclds.stream().collect(Collectors.toMap(PhotovoltaicInfo::getInverter, Function.identity()));
+
+        String fs = config.getFilePathPrepare() + "gf" + File.separator;
+        Map<String, List<PhotovoltaicInfo>> stringListMap = new HashMap<>();
+        for (String s : fileList) {
+            //读取一个文件
+            List<PhotovoltaicInfo> infos = file2Info(fs + s, true);
+            List<PhotovoltaicInfo> theoryInfos;
+            if (s.contains("HZJ_GDC") || s.contains("AK_GDC")) {
+                theoryInfos = CurrentVoltageCalc.CalcTheoryPowerHZJ(infos, bzcldMap);
+            } else {
+                theoryInfos = CurrentVoltageCalc.CalcTheoryPower(infos, bzcldMap);
+            }
+            //按逆变器聚合数据
+            if (stringListMap.containsKey(theoryInfos.get(0).getInverter())) {
+                stringListMap.get(theoryInfos.get(0).getInverter()).addAll(theoryInfos);
+
+            } else {
+                stringListMap.put(theoryInfos.get(0).getInverter(), theoryInfos);
+            }
+        }
+        return stringListMap;
+    }
+
+    /**
+     * 计算理论功率加入原列表
+     *
+     * @return
+     */
+    public Map<String, List<PhotovoltaicInfo>> calculatAnalysis1(List<PhotovoltaicInfo> bzdList, Map<String, List<PhotovoltaicInfo>> datasInfos) {
+
+        Map<String, PhotovoltaicInfo> bzcldMap = bzdList.stream().collect(Collectors.toMap(PhotovoltaicInfo::getInverter, Function.identity()));
+
+        Map<String, List<PhotovoltaicInfo>> stringListMap = new HashMap<>();
+
+        String s;
+        for (Map.Entry<String, List<PhotovoltaicInfo>> entry : datasInfos.entrySet()) {
+            s = entry.getKey();
+            List<PhotovoltaicInfo> theoryInfos;
+            if (s.contains("HZJ_GDC") || s.contains("AK_GDC")) {
+                theoryInfos = CurrentVoltageCalc.CalcTheoryPowerHZJ(entry.getValue(), bzcldMap);
+            } else {
+                theoryInfos = CurrentVoltageCalc.CalcTheoryPower(entry.getValue(), bzcldMap);
+            }
+            stringListMap.put(s, theoryInfos);
+        }
+        return stringListMap;
+    }
+
+    //    public Map<String, List<PhotovoltaicInfo>> calculatAnalysis1(List<List<List<PhotovoltaicInfo>>> feill) {
+    //
+    //        String bzcldPath = config.getFilePathPrepare() + "bzd"+File.separator + "标准点.csv";
+    //        List<PhotovoltaicInfo> bzclds = file2Info(bzcldPath, true);
+    //        Map<String, PhotovoltaicInfo> bzcldMap = bzclds.stream().collect(Collectors.toMap(PhotovoltaicInfo::getInverter, Function.identity()));
+    //
+    //        String fs = config.getFilePathPrepare() + "gf" +File.separator;
+    //        Map<String, List<PhotovoltaicInfo>> stringListMap = new HashMap<>();
+    //        for (String s : fileList) {
+    //            //读取一个文件
+    //            List<PhotovoltaicInfo> infos = file2Info(fs + s, true);
+    //            List<PhotovoltaicInfo> theoryInfos;
+    //            if (s.contains("HZJ_GDC") || s.contains("AK_GDC")) {
+    //                theoryInfos = CurrentVoltageCalc.CalcTheoryPowerHZJ(infos, bzcldMap);
+    //            } else {
+    //                theoryInfos = CurrentVoltageCalc.CalcTheoryPower(infos, bzcldMap);
+    //            }
+    //            //按逆变器聚合数据
+    //            if (stringListMap.containsKey(theoryInfos.get(0).getInverter())) {
+    //                stringListMap.get(theoryInfos.get(0).getInverter()).addAll(theoryInfos);
+    //
+    //            } else {
+    //                stringListMap.put(theoryInfos.get(0).getInverter(), theoryInfos);
+    //            }
+    //        }
+    //        return stringListMap;
+    //    }
+
+    /**
+     * 合并同逆变器文件
+     *
+     * @param fileList
+     * @return
+     */
+    public Map<String, List<PhotovoltaicInfo>> mergeCalculat(List<String> fileList) {
+
+        String fs = config.getFilePathPrepare() + "gf" + File.separator;
+        Map<String, List<PhotovoltaicInfo>> stringListMap = new HashMap<>();
+        for (String s : fileList) {
+            //读取一个文件
+            List<PhotovoltaicInfo> infos = file2Info(fs + s, true);
+            //按逆变器聚合数据
+            if (stringListMap.containsKey(infos.get(0).getInverter())) {
+                stringListMap.get(infos.get(0).getInverter()).addAll(infos);
+            } else {
+                stringListMap.put(infos.get(0).getInverter(), infos);
+            }
+        }
+        return stringListMap;
+    }
+
+    public List<Object> str2FileList(List<String> fileList) {
+        List<ProEconPowerFittingAnalySis> fileLists = new ArrayList<>();
+        for (String s : fileList) {
+            String[] split = s.split("-");
+            ProEconPowerFittingAnalySis fl = new ProEconPowerFittingAnalySis();
+            /*fl.setPath(s);
+            fl.setStation(split[0]);
+            fl.setStationcn(InitialRunner.gfstationMap.get(split[0]));
+            fl.setWindturbine(split[1]);
+            fl.setTime(split[2]+"年"+split[3]+"月");
+            fl.setInterval("五分钟");*/
+            fl.setPath(s);
+            fl.setStation(split[0]);
+            fl.setStationcn(split[1]);
+            //fl.setWindturbine(split[1]);
+            fl.setTime(InitialRunner.newgfstationMap.get(split[0]));
+            fl.setInterval(split[2] + "年" + split[3] + "月");
+            fileLists.add(fl);
+        }
+        List<Object> objects = PowerFittingUtil.powerDataTree(fileLists, Constants.DATA_FITTING);
+        return objects;
+    }
+
+    public List<String> getAllFileList() {
+        //获取文件位置
+        File file = new File(config.getFilePathPrepare() + "gf" + "一秒");
+        //获取文件列表
+        File[] files = file.listFiles();
+        List<String> fileList = Arrays.stream(files).map(f -> f.getName()).collect(Collectors.toList());
+        return fileList;
+    }
+
+    /**
+     * 标准点计算
+     */
+    public void standardPointCalculate2() {
+        List<String> allFileList = getAllFileList();
+        Map<String, List<PhotovoltaicInfo>> stringListMap = mergeCalculat(allFileList);
+
+        List<PhotovoltaicInfo> ptInfos = new ArrayList<>();
+        for (Map.Entry<String, List<PhotovoltaicInfo>> entry : stringListMap.entrySet()) {
+            List<PhotovoltaicInfo> value = entry.getValue();
+            Optional<PhotovoltaicInfo> first = value.stream().sorted(Comparator.comparing(PhotovoltaicInfo::getActualP).reversed()).findFirst();
+            ptInfos.add(first.get());
+        }
+
+        //文件第一行
+        List<FixedVo> fixedVos = AnnotationTool.getFixedVoList(PhotovoltaicInfo.class);
+        StringBuilder sb = new StringBuilder();
+        String columnName = fixedVos.stream().map(FixedVo::getDes).collect(Collectors.joining(","));
+        sb.append(columnName).append("\n");
+        for (PhotovoltaicInfo ptInfo : ptInfos) {
+            sb.append(ptInfo.getStation()).append(",").append(ptInfo.getInverter()).append(",")
+                    .append(DateUtils.date2StringL(new Date(ptInfo.getTime()))).append(",")
+                    .append(ptInfo.getT()).append(",").append(ptInfo.getS()).append(",")
+                    .append(ptInfo.getI()).append(",").append(ptInfo.getV())
+                    .append(",").append(ptInfo.getActualP()).append(",")
+                    .append(ptInfo.getAI()).append(",").append(ptInfo.getAV())
+                    .append(",").append(ptInfo.getBI()).append(",").append(ptInfo.getBV())
+                    .append(",").append(ptInfo.getCI()).append(",").append(ptInfo.getCV())
+                    .append("\n");
+        }
+        String fileName = config.getFilePathPrepare() + "bzd" + File.separator + "标准点.csv";
+        File file = new File(fileName);
+        file.delete();
+        FileUtil.writeFile(fileName, sb.toString());
+
+    }
+
+    /**
+     * 标准点计算
+     *
+     * @param stringListMap
+     */
+    public List<PhotovoltaicInfo> standardPointCalculate1(Map<String, List<PhotovoltaicInfo>> stringListMap) {
+
+        List<PhotovoltaicInfo> ptInfos = new ArrayList<>();
+        for (Map.Entry<String, List<PhotovoltaicInfo>> entry : stringListMap.entrySet()) {
+            List<PhotovoltaicInfo> value = entry.getValue();
+            Optional<PhotovoltaicInfo> first = value.stream().sorted(Comparator.comparing(PhotovoltaicInfo::getActualP).reversed()).findFirst();
+            ptInfos.add(first.get());
+        }
+        return ptInfos;
+    }
+
+    public List<TableTitle> getTheoryTitel() {
+
+        List<FixedVo> fixedVos = AnnotationTool.getFixedVoList(PhotovoltaicInfo.class);
+        String[] ss = {"station", "datetime", "T", "S", "actualP"};
+        List<String> strings = Arrays.asList(ss);
+        List<TableTitle> collect = fixedVos.stream().map(d -> new TableTitle(d.getName(), d.getDes())).collect(Collectors.toList());
+        collect = collect.stream().filter(c -> strings.contains(c.getKey())).collect(Collectors.toList());
+        TableTitle title = new TableTitle();
+        title.setKey("ideaP");
+        title.setDes("理论功率");
+        collect.add(title);
+
+        return collect;
+    }
+
+    /**
+     * 获得所有文件的值
+     *
+     * @param fileList
+     * @return
+     */
+    public List<PhotovoltaicInfo> calculatFitting(List<String> fileList) {
+
+        String fs = config.getFilePathPrepare() + "gf" + File.separator;
+        List<PhotovoltaicInfo> infoList = new ArrayList<>();
+        for (String s : fileList) {
+            List<PhotovoltaicInfo> infos = file2Info(fs + s, true);
+            if (infoList.size() == 0 || Objects.equals(infos.get(0).getStation(), infoList.get(0).getStation())) {
+                infoList.addAll(infos);
+            }
+        }
+
+        return infoList;
+    }
+
+    public List<double[]> oneFileFitting(List<PhotovoltaicInfo> infos) {
+
+        WeightedObservedPoints points = new WeightedObservedPoints();
+        double max = 0;
+        for (PhotovoltaicInfo info : infos) {
+            if (info.getS() < 1) {
+                points.add(0, 0);
+            }
+            points.add(info.getS(), info.getActualP());
+            if (info.getS() > max) {
+                max = info.getS();
+            }
+        }
+        double[] result = pncf.run(points);
+
+        List<double[]> b = new ArrayList<>();
+        for (int i = 0; i < max; i += 5) {
+            double[] curve = new double[2];
+            curve[0] = i;
+            curve[1] = pncf.calcPoly(i, result);
+            b.add(curve);
+        }
+        return b;
+    }
+
+    /**
+     * 光伏绩效榜
+     *
+     * @param startdate
+     * @param enddate
+     */
+    public List<FjjxbVo> getPhotovoltaicPerformanceList(long startdate, long enddate, int interval) {
+        int oneday = 24 * 60 * 60;
+
+        String bzcldPath = config.getFilePathPrepare() + "bzd" + File.separator + "标准点.csv";
+        List<PhotovoltaicInfo> bzclds = file2Info(bzcldPath, true);
+        Map<String, PhotovoltaicInfo> bzcldMap = bzclds.stream().collect(Collectors.toMap(PhotovoltaicInfo::getInverter, Function.identity()));
+
+        //获取实际发电量
+        List<ProBasicPowerstationPoint> rfdl = proBasicPowerstationPointService.getzfsPoints(null, "RFDL");
+        List<FjjxbVo> infos = new ArrayList<>();
+        //遍历逆变器
+        for (ProBasicPowerstationPoint wstp : rfdl) {
+            //场站
+            String stationid = wstp.getWindpowerstationId();
+
+            List<TsDoubleData> history = remoteService.adapterfd().getHistorySnap(wstp.getNemCode(), startdate + oneday * 1000, enddate, oneday);
+            double d = 0;
+            for (TsDoubleData data : history) {
+                d += data.getDoubleValue();
+            }
+            FjjxbVo vo = new FjjxbVo();
+            vo.setName(InitialRunner.newgfstationMap.get(stationid));
+            vo.setSjfdl(d);
+
+            //理论发电量
+            double llfdl = 0;
+            //光照平均值
+            double gz = 0;
+            int i = 0;
+            double t = 5 / 60;
+
+            List<List<PhotovoltaicInfo>> datas = getDatas(stationid, startdate, enddate, interval);
+            //遍历逆变器
+            for (List<PhotovoltaicInfo> data : datas) {
+
+                if ("HZJ_GDC".equals(stationid) || "AK_GDC".equals(stationid)) {
+                    CurrentVoltageCalc.CalcTheoryPowerHZJ(data, bzcldMap);
+                } else {
+                    CurrentVoltageCalc.CalcTheoryPower(data, bzcldMap);
+                }
+
+                for (PhotovoltaicInfo datum : data) {
+                    llfdl += datum.getIdeaP() * t;
+                    gz += datum.getS();
+                    i++;
+                }
+            }
+            vo.setLlfdl(llfdl);
+            vo.setSpeed(gz / i);
+            vo.setFnlly(vo.getSjfdl() / vo.getLlfdl() * 100);
+            infos.add(vo);
+        }
+        return infos;
+    }
+
+    /**
+     * 获取数据
+     *
+     * @return 逆变器,列表
+     */
+    public List<List<PhotovoltaicInfo>> getDatas(String stationid, long start, long end, Integer interval) {
+        //间隔
+        if (interval == null)
+            interval = 5 * 60; //5分钟-300
+
+        //获得测点
+        Map<String, String> zglpoints = getPoints(stationid, "zgl");
+        Map<String, String> llglpoints = getPoints(stationid, "llgl");
+        Map<String, String> adypoints = getPoints(stationid, "ady");
+        Map<String, String> bdypoints = getPoints(stationid, "bdy");
+        Map<String, String> cdypoints = getPoints(stationid, "cdy");
+        Map<String, String> adlpoints = getPoints(stationid, "adl");
+        Map<String, String> bdlpoints = getPoints(stationid, "bdl");
+        Map<String, String> cdlpoints = getPoints(stationid, "cdl");
+
+        List<ProBasicWeatherStation> weatherStations = weatherStationService.getBaseMapper().selectList(null);
+        List<ProBasicWeatherStation> collect = weatherStations.stream().filter(c -> stationid.equals(c.getWindpowerstationId())).collect(Collectors.toList());
+
+        String station = collect.get(0).getId();
+
+        ProBasicPowerstationPoint zfsPoint = InitialRunner.newzfsMap.get(stationid);
+        ProBasicPowerstationPoint zjwdPoint = InitialRunner.newzjwdMap.get(station);
+
+        //总辐射
+        //        List<TsDoubleData> zfsDatas = adpClient.getHistorySnap(zfsPoint.getNemCode(), start, end, interval);
+
+        List<TsDoubleData> zfsDatas = remoteService.adapterfd().getHistorySnap(zfsPoint.getNemCode(), start, end, interval);
+
+        //组件温度
+        //        List<TsDoubleData> zjwdDatas = adpClient.getHistorySnap(zjwdPoint.getNemCode(), start, end, interval);
+
+        List<TsDoubleData> zjwdDatas = remoteService.adaptergf().getHistorySnap(zjwdPoint.getNemCode(), start, end, interval);
+
+        List<List<PhotovoltaicInfo>> infosLit = new ArrayList<>();
+        //按逆变器
+        for (String wtid : zglpoints.keySet()) {
+
+            //总功率
+            //            List<TsDoubleData> zglDatas = adpClient.getHistorySnap(zglpoints.get(wtid), start, end, interval);
+            List<TsDoubleData> zglDatas = remoteService.adaptergf().getHistorySnap(zglpoints.get(wtid), start, end, interval);
+            List<TsDoubleData> llglDatas = remoteService.adapterfd().getHistorySnap(llglpoints.get(wtid), start, end, interval);
+
+            //电网A相电压
+            //            List<TsDoubleData> adyDatas = adpClient.getHistorySnap(adypoints.get(wtid), start, end, interval);
+            List<TsDoubleData> adyDatas = remoteService.adaptergf().getHistorySnap(adypoints.get(wtid), start, end, interval);
+            //电网A相电流
+            //            List<TsDoubleData> adlDatas = adpClient.getHistorySnap(adlpoints.get(wtid), start, end, interval);
+            List<TsDoubleData> adlDatas = remoteService.adaptergf().getHistorySnap(adlpoints.get(wtid), start, end, interval);
+
+            List<PhotovoltaicInfo> infos = new ArrayList<>();
+
+            List<TsDoubleData> bdyDatas = null, cdyDatas = null, bdlDatas = null, cdlDatas = null;
+            if ("HZJ_GDC".equals(stationid) || "AK_GDC".equals(stationid)) {
+                //电网B相电压
+                bdyDatas = adpClient.getHistorySnap(bdypoints.get(wtid), start, end, interval);
+                //电网C相电压
+                cdyDatas = adpClient.getHistorySnap(cdypoints.get(wtid), start, end, interval);
+                //电网B相电流
+                bdlDatas = adpClient.getHistorySnap(bdlpoints.get(wtid), start, end, interval);
+                //电网C相电流
+                cdlDatas = adpClient.getHistorySnap(cdlpoints.get(wtid), start, end, interval);
+            }
+
+            for (int j = 0; j < zfsDatas.size(); j++) {
+                PhotovoltaicInfo info = new PhotovoltaicInfo();
+                info.setStation(stationid);
+                info.setInverter(wtid);
+                long ts = zfsDatas.get(j).getTs();
+                info.setTime(ts);
+                info.setDatetime(DateUtils.date2StringL(new Date(ts)));
+
+                info.setT(double3Decimal(zjwdDatas.get(j).getDoubleValue()));
+                info.setS(double3Decimal(zfsDatas.get(j).getDoubleValue(), false));
+                if ("HZJ_GDC".equals(stationid) || "AK_GDC".equals(stationid)) {
+                    info.setAI(double3Decimal(adlDatas.get(j).getDoubleValue(), false));
+                    info.setBI(double3Decimal(bdlDatas.get(j).getDoubleValue(), false));
+                    info.setCI(double3Decimal(cdlDatas.get(j).getDoubleValue(), false));
+                    info.setAV(double3Decimal(adyDatas.get(j).getDoubleValue(), true));
+                    info.setBV(double3Decimal(bdyDatas.get(j).getDoubleValue(), true));
+                    info.setCV(double3Decimal(cdyDatas.get(j).getDoubleValue(), true));
+                } else {
+                    if (adlDatas.size() >= 1) {
+                        info.setI(double3Decimal(adlDatas.get(j).getDoubleValue(), false));
+                    } else {
+                        info.setI(0);
+                    }
+                    if (adyDatas.size() >= 1) {
+                        info.setV(double3Decimal(adyDatas.get(j).getDoubleValue(), true));
+                    } else {
+                        info.setV(0);
+                    }
+                }
+                if (zglDatas.size() >= 1) {
+                    info.setActualP(double3Decimal(zglDatas.get(j).getDoubleValue(), false));
+                } else {
+                    info.setActualP(0);
+                }
+                if (llglDatas.size() >= 1) {
+                    info.setIdeaP(double3Decimal(llglDatas.get(j).getDoubleValue(), false));
+                } else {
+                    info.setIdeaP(0);
+                }
+                infos.add(info);
+            }
+            infosLit.add(infos);
+        }
+
+        return infosLit;
+    }
+
+    private double double3Decimal(double d) {
+        BigDecimal bd = new BigDecimal(d);
+        return bd.setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue();
+    }
+
+    private double double3Decimal(double d, boolean isMultFactor) {
+        d = d < 1 ? 0 : d;
+        if (isMultFactor) {
+            d = d * 0.001;
+        }
+        return double3Decimal(d);
+    }
+
+    /**
+     * 获得测点
+     * 逆变器,测点
+     */
+    private Map<String, String> getPoints(String stationid, String key) {
+
+        switch (key) {
+            case "zgl":
+                //总功率
+                return InitialRunner.newzglMap.get(stationid).stream().filter(c -> !c.getNemCode().equals("INTIAL")).collect(Collectors.toMap(ProBasicEquipmentPoint::getWindturbineId, ProBasicEquipmentPoint::getNemCode));
+            case "llgl":
+                //总功率
+                return InitialRunner.newllglMap.get(stationid).stream().filter(c -> !c.getNemCode().equals("INTIAL")).collect(Collectors.toMap(ProBasicEquipmentPoint::getWindturbineId, ProBasicEquipmentPoint::getNemCode));
+
+            case "ady":
+                List<ProBasicEquipmentPoint> adyPoints = null;
+                if ("HZJ_GDC".equals(stationid)) {
+                    //电网A相电压
+                    adyPoints = proBasicEquipmentPointService.getPoints(stationid, null, "AIG005");
+                } else {
+                    //电网A相电压
+                    adyPoints = proBasicEquipmentPointService.getPoints(stationid, null, "AIG005");
+                }
+
+                return adyPoints.stream().filter(c -> !c.getNemCode().equals("INTIAL")).collect(Collectors.toMap(ProBasicEquipmentPoint::getWindturbineId, ProBasicEquipmentPoint::getNemCode));
+            case "bdy":
+                List<ProBasicEquipmentPoint> bdyPoints = proBasicEquipmentPointService.getPoints(stationid, null, "AIG008");
+                return bdyPoints.stream().filter(c -> !c.getNemCode().equals("INTIAL")).collect(Collectors.toMap(ProBasicEquipmentPoint::getWindturbineId, ProBasicEquipmentPoint::getNemCode));
+            case "cdy":
+                List<ProBasicEquipmentPoint> cdyPoints = proBasicEquipmentPointService.getPoints(stationid, null, "AIG011");
+                return cdyPoints.stream().filter(c -> !c.getNemCode().equals("INTIAL")).collect(Collectors.toMap(ProBasicEquipmentPoint::getWindturbineId, ProBasicEquipmentPoint::getNemCode));
+            case "adl":
+                List<ProBasicEquipmentPoint> adlPoints = proBasicEquipmentPointService.getPoints(stationid, null, "AIG004");
+                return adlPoints.stream().filter(c -> !c.getNemCode().equals("INTIAL")).collect(Collectors.toMap(ProBasicEquipmentPoint::getWindturbineId, ProBasicEquipmentPoint::getNemCode));
+            case "bdl":
+                List<ProBasicEquipmentPoint> bdlPoints = proBasicEquipmentPointService.getPoints(stationid, null, "AIG007");
+                return bdlPoints.stream().filter(c -> !c.getNemCode().equals("INTIAL")).collect(Collectors.toMap(ProBasicEquipmentPoint::getWindturbineId, ProBasicEquipmentPoint::getNemCode));
+            case "cdl":
+                List<ProBasicEquipmentPoint> cdlPoints = proBasicEquipmentPointService.getPoints(stationid, null, "AIG010");
+                return cdlPoints.stream().filter(c -> !c.getNemCode().equals("INTIAL")).collect(Collectors.toMap(ProBasicEquipmentPoint::getWindturbineId, ProBasicEquipmentPoint::getNemCode));
+        }
+        return new HashMap<>();
+    }
+
+    public int deleteFiles(List<String> fileList) {
+        String fs = config.getFilePathPrepare() + "gf";
+        List<PhotovoltaicInfo> infoList = new ArrayList<>();
+        int count = 0;
+        for (String s : fileList) {
+            File file = new File(fs + s);
+            if (file.delete()) count++;
+        }
+        return count;
+    }
+
+    public void downFiles(List<String> strings, HttpServletResponse response) {
+        List<File> files = path2File(strings);
+        String path = config.getFilePathPrepare() + "zip\\" + System.currentTimeMillis() + ".zip";
+        String s = FileUtil.zipFiles(files, new File(path));
+        FileUtil.download(s, response);
+    }
+
+    private List<File> path2File(List<String> strings) {
+        List<File> files = new ArrayList<>();
+        for (String string : strings) {
+            files.add(new File(config.getFilePathPrepare() + "gf" + string));
+        }
+        return files;
+    }
+
+    public List<FixedVo> getFixedVos() {
+        if (fixedVos == null) {
+            fixedVos = AnnotationTool.getFixedVoList(PhotovoltaicInfo.class);
+            uniforcodes = fixedVos.stream().filter(fv -> fv.getUniformCode() != null).collect(Collectors.toMap(FixedVo::getDes, FixedVo::getUniformCode));
+        }
+        return fixedVos;
+    }
+
+    public Map<String, String> getUniforcodes() {
+        getFixedVos();
+        return uniforcodes;
+    }
+
+
+    public List<ProBasicEquipment> wtByWplist(String wpids) {
+        List<ProBasicEquipment> equipmentList = InitialRunner.newgfwtList.stream()
+                .filter(oe -> wpids.contains(oe.getWindpowerstationId()))
+                .sorted(Comparator.comparingInt(ProBasicEquipment::getOrderNum)) // 根据order_num字段排序
+                .collect(Collectors.toList());
+
+        return equipmentList;
+    }
+
+    /**
+     * 通过大点的key获取小散点
+     *
+     * @param yk
+     * @param wk
+     * @return
+     */
+    public List<PhotovoltaicInfo> dataOrigin(String yk, String wk) {
+        List<PhotovoltaicInfo> list = new ArrayList<>();
+
+        if (!StringUtils.isEmpty(yk)) {
+            String[] key = yk.split(",");
+            for (String k : key) {
+                list.addAll(dataScangfService.getMapYY().get(k));
+            }
+        }
+        if (!StringUtils.isEmpty(wk)) {
+            String[] kew = wk.split(",");
+            for (String k : kew) {
+                list.addAll(dataScangfService.getMapWY().get(k));
+            }
+        }
+
+        return list;
+    }
+}

+ 20 - 0
power-fitting-JN/src/main/java/com.gyee.power.fitting/service/impl/PhotovoltaicAnalysisServiceImpl.java

@@ -0,0 +1,20 @@
+package com.gyee.power.fitting.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.gyee.power.fitting.mapper.PhotovoltaicAnalysisMapper;
+import com.gyee.power.fitting.model.PhotovoltaicAnalysis;
+import com.gyee.power.fitting.service.IPhotovoltaicAnalysisService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 光伏分析 服务实现类
+ * </p>
+ *
+ * @author gfhd
+ * @since 2023-10-13
+ */
+@Service
+public class PhotovoltaicAnalysisServiceImpl extends ServiceImpl<PhotovoltaicAnalysisMapper, PhotovoltaicAnalysis> implements IPhotovoltaicAnalysisService {
+
+}