Procházet zdrojové kódy

市自来水更新:
1.市自来水五个片区15分钟单位的实际数据采集
2.15分钟单位实际数据查询接口
3.15分钟单位预测数据查询接口
4.定时任务新增片区和分区站点的15分钟单位的数据采集,每五分钟获取一次
5.实现15分钟预测插值并实现拆分平滑处理

1037015548@qq.com před 1 měsícem
rodič
revize
f7ade93382
15 změnil soubory, kde provedl 1414 přidání a 45 odebrání
  1. 8 8
      sql.properties
  2. 567 10
      src/main/java/com/shkpr/service/aimodelpower/bizmgr/KprAimTapWaterBizFun.java
  3. 262 1
      src/main/java/com/shkpr/service/aimodelpower/bizmgr/KprAimWaterCollecationBizFun.java
  4. 2 0
      src/main/java/com/shkpr/service/aimodelpower/constants/ApiURI.java
  5. 134 4
      src/main/java/com/shkpr/service/aimodelpower/controllerapi/WaterCollecationController.java
  6. 2 0
      src/main/java/com/shkpr/service/aimodelpower/controllerfilter/third/ThirdJWTCurrencyFilter.java
  7. 19 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/shizilaishuiDataSource/WaterCollecationDao.java
  8. 132 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/shizilaishuiDataSource/WaterZILAISHUIDao.java
  9. 20 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/shizilaishuiDataSource/service/WaterCollecationServiceImpl.java
  10. 103 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/shizilaishuiDataSource/service/WaterTapWaterServiceImpl.java
  11. 2 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/shizilaishuiDataSource/service/intef/WaterCollecationService.java
  12. 11 0
      src/main/java/com/shkpr/service/aimodelpower/dbdao/shizilaishuiDataSource/service/intef/WaterTapWaterService.java
  13. 32 16
      src/main/java/com/shkpr/service/aimodelpower/globalmgr/ScheduleTaskMgr.java
  14. 106 0
      src/main/java/com/shkpr/service/aimodelpower/jsonbean/zilaishui/JPTbMMinutesWater.java
  15. 14 6
      src/main/resources/application.properties

+ 8 - 8
sql.properties

@@ -5,18 +5,18 @@ spring.datasource.data.password=kpr.23417.postgres
 spring.datasource.data.driver-class-name=org.postgis.DriverWrapper
 
 #pgsql Ë®Á¿Ô¤²âÊý¾Ý¿âÔ´
-#spring.datasource.db2.jdbc-url=jdbc:postgresql_postGIS://140.246.183.164:5432/water_volume_prediction?useSSL=false&useAffectedRows=false&allowMultiQueries=true
-#spring.datasource.db2.username=postgres
-#spring.datasource.db2.password=kpr.23417.postgres
+spring.datasource.db2.jdbc-url=jdbc:postgresql_postGIS://140.246.183.164:5432/water_volume_prediction?useSSL=false&useAffectedRows=false&allowMultiQueries=true
+spring.datasource.db2.username=postgres
+spring.datasource.db2.password=kpr.23417.postgres
 #spring.datasource.db2.driver-class-name=org.postgis.DriverWrapper
 #spring.datasource.db2.jdbc-url=jdbc:postgresql_postGIS://10.101.5.50:5432/water_volume_prediction?useSSL=false&useAffectedRows=false&allowMultiQueries=true
-spring.datasource.db2.jdbc-url=jdbc:postgresql_postGIS://10.101.3.104:5432/water_volume_prediction_jiangjin2?useSSL=false&useAffectedRows=false&allowMultiQueries=true
-spring.datasource.db2.username=postgres
+#spring.datasource.db2.jdbc-url=jdbc:postgresql_postGIS://10.101.3.104:5432/water_volume_prediction_jiangjin2?useSSL=false&useAffectedRows=false&allowMultiQueries=true
+#spring.datasource.db2.username=postgres
 #spring.datasource.db2.password=ygt.23417.postgres
-spring.datasource.db2.password=kpr.23417.postgres
+#spring.datasource.db2.password=kpr.23417.postgres
 spring.datasource.db2.driver-class-name=org.postgis.DriverWrapper
-spring,database.name=water_volume_prediction_jiangjin2
-#spring,database.name=water_volume_prediction
+#spring,database.name=water_volume_prediction_jiangjin2
+spring,database.name=water_volume_prediction
 
 spring.datasource.child2pg.jdbc-url=jdbc:postgresql_postGIS://10.101.5.50:5432/water_level_prediction?useSSL=false&useAffectedRows=false&allowMultiQueries=true
 spring.datasource.child2pg.username=postgres

+ 567 - 10
src/main/java/com/shkpr/service/aimodelpower/bizmgr/KprAimTapWaterBizFun.java

@@ -6,6 +6,7 @@ import com.global.base.log.LogPrintMgr;
 import com.global.base.tools.FastJsonUtil;
 import com.shkpr.service.aimodelpower.commtools.TimeTool;
 import com.shkpr.service.aimodelpower.dbdao.DBMgrProxy;
+import com.shkpr.service.aimodelpower.dbdao.shizilaishuiDataSource.service.intef.WaterCollecationService;
 import com.shkpr.service.aimodelpower.dbdao.shizilaishuiDataSource.service.intef.WaterTapWaterService;
 import com.shkpr.service.aimodelpower.dto.TraceRunnable;
 import com.shkpr.service.aimodelpower.globalmgr.ThreadTaskMgr;
@@ -13,8 +14,13 @@ import com.shkpr.service.aimodelpower.globalmgr.TraceLogMgr;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.ObjectUtils;
 
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.time.Duration;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.LocalTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.concurrent.CountDownLatch;
@@ -36,7 +42,558 @@ public class KprAimTapWaterBizFun {
     public static WaterTapWaterService getWaterTapWaterApi(){
         return DBMgrProxy.getInstance().applyWaterTapWaterService();
     }
+
+    public static WaterCollecationService getWaterCollecationApi(){
+        return DBMgrProxy.getInstance().applyWaterCollecationService();
+    }
     static DateTimeFormatter formater = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+    //TODO 15分间隔的预测插值(做假暂时用,不用时注释)
+    //TODO 思路:等预测小时的原程序完成后, 原预测表中为小时预测数据,分钟字段为空,将预测表中的数据进行二次清洗然后插入新预测表
+    //TODO beforeDays为往前推清洗多少天 n-1为逻辑, 例如传1就是0天当天
+    public static void yuceZuojia(int beforeDays){
+        try{
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"预测15分钟插值开始时间:"+TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT));
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"预测15分钟插值进行中:......");
+            List<Map<String, Object>> orgConfig = getWaterCollecationApi().getOrgConfig(false, 0, 0, " AND org_name not like '%营业所' and (org_name!='北碚水厂' and org_name!='渝中区水厂')");
+            final CountDownLatch latch = new CountDownLatch(orgConfig.size());
+            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+            LocalDateTime startDate = LocalDateTime.now().withMinute(0).withSecond(0);
+            for (Map<String,Object> org:orgConfig) {
+                ThreadTaskMgr.runTask(new TraceRunnable(TraceLogMgr.getTraceId()) {
+                    @Override
+                    public void function() {
+                        try {
+                            for (int dayNum=0;dayNum<beforeDays;dayNum++) {
+                                List<Map<String, Object>> resHourList = getWaterCollecationApi().getTbMHourwater(false,
+                                        20, 0, " AND \"orgId\" = '" + org.get("org_id") + "' AND \"Date\" = '" + startDate.minusDays(-dayNum).format(formatter) + "' ORDER BY \"Date\",\"Hour\" ASC ");
+                                processWaterData(resHourList);
+                            }
+                            latch.countDown();
+                        }catch(Exception ex){
+                            ex.printStackTrace();
+                        }
+                    }
+                });
+            }
+            latch.await();
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"预测15分钟插值已结束");
+        }catch(Exception ex){
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR
+                    , mStrClassName
+                    , mStrClassName
+                    , String.format("Batch yuceZuojia ERROR:{%s} "
+                            , ex.getLocalizedMessage()));
+        }
+    }
+    private static DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+    private static DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
+    public static void processWaterData(List<Map<String, Object>> resHourList) {
+        List<List<Map<String, Object>>> trendGroups = new ArrayList<>();
+        List<Map<String, Object>> currentGroup = new ArrayList<>();
+
+        for (int i = 0; i < resHourList.size(); i++) {
+            Map<String, Object> currentMap = resHourList.get(i);
+            double currentHourData = getDoubleValue(currentMap, "HourForecastActualWaterSupply");
+
+            if (i == 0) {
+                currentGroup.add(currentMap);
+            } else {
+                double previousHourData = getDoubleValue(resHourList.get(i - 1), "HourForecastActualWaterSupply");
+
+                boolean isIncreasing = currentHourData > previousHourData;
+                if (currentGroup.size() > 0) {
+                    double lastGroupData = getDoubleValue(currentGroup.get(currentGroup.size() - 1), "HourForecastActualWaterSupply");
+                    boolean wasIncreasing = lastGroupData < currentHourData;
+
+                    if (isIncreasing != wasIncreasing) {
+                        trendGroups.add(new ArrayList<>(currentGroup));
+                        currentGroup.clear();
+                    }
+                }
+                currentGroup.add(currentMap);
+            }
+        }
+
+        if (!currentGroup.isEmpty()) {
+            trendGroups.add(currentGroup);
+        }
+
+        for (List<Map<String, Object>> group : trendGroups) {
+            for (int i = 0; i < group.size() - 1; i++) {
+                Map<String, Object> currentMap = group.get(i);
+                double currentHourData = getDoubleValue(currentMap, "HourForecastActualWaterSupply");
+                double nextHourData = getDoubleValue(group.get(i + 1), "HourForecastActualWaterSupply");
+
+                boolean isIncreasing = nextHourData > currentHourData;
+                double[] splitData = splitHourData(currentHourData, isIncreasing);
+                // 步骤2:平滑处理
+                double alpha = 0.3; // 平滑系数
+                double[] smoothedData = exponentialSmoothing(splitData,alpha);
+
+                // 解析日期字符串
+                LocalDate date = LocalDate.parse(currentMap.get("Date").toString(), DateTimeFormatter.ISO_LOCAL_DATE);
+                // 解析时间字符串
+                LocalTime time = LocalTime.parse(currentMap.get("Hour").toString(), DateTimeFormatter.ISO_LOCAL_TIME);
+                LocalDateTime dateTime = LocalDateTime.of(date, time).minusMinutes(45);
+
+                for (int j = 0; j < smoothedData.length; j++) {
+                    Map<String, Object> newMap = new HashMap<>(currentMap);
+                    newMap.put("HourForecastActualWaterSupply", smoothedData[j]);
+                    LocalDateTime quarterHourTime = dateTime.plusMinutes(j * 15);
+                    newMap.put("Date", quarterHourTime.format(dateFormatter));
+                    newMap.put("Hour", quarterHourTime.format(timeFormatter));
+
+                    // Here you would query the database and insert/update data
+                    // For example:
+                    double originalValue = queryOriginalValue(quarterHourTime);
+                    newMap.put("HourActualWaterSupply", originalValue);
+
+                    // Retain only specific keys
+                    Map<String, Object> filteredMap = filterMap(newMap, "Date", "Hour", "HourForecastActualWaterSupply", "HourActualWaterSupply", "LastModifyTime", "orgId");
+
+                    // Insert or update the database
+                    // int insertRes = insertOrUpdateDatabase(filteredMap);
+                    // Handle the result if needed
+                    Integer insertRes = getWaterTapWaterApi().insertOrUpdateTbmHourWaterNew(filteredMap);
+                    if (insertRes < 1) {
+                        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR
+                                , mStrClassName
+                                , mStrClassName
+                                , String.format("Batch yuceZuojia ERROR:{%s} ",
+                                        "新增或修改失败"));
+                    }
+                }
+            }
+        }
+    }
+
+    private static double getDoubleValue(Map<String, Object> map, String key) {
+        Object value = map.get(key);
+        return value != null ? Double.parseDouble(value.toString()) : 0.0;
+    }
+    //拆分函数
+    private static double[] splitHourData(double hourData, boolean isIncreasing) {
+        double[] splitData = new double[4];
+        if (isIncreasing) {
+            // 调整比例以实现更平滑的上升曲线
+            splitData[0] = hourData * 0.24;
+            splitData[1] = hourData * 0.26;
+            splitData[2] = hourData * 0.25;
+            splitData[3] = hourData * 0.25;
+        } else {
+            // 调整比例以实现更平滑的下降曲线
+            splitData[0] = hourData * 0.25;
+            splitData[1] = hourData * 0.25;
+            splitData[2] = hourData * 0.26;
+            splitData[3] = hourData * 0.24;
+        }
+        return splitData;
+    }
+    //平滑函数
+    private static double[] smoothData(double[] data) {
+        double[] smoothedData = new double[data.length];
+        int windowSize = 3; // 移动平均窗口大小
+        for (int i = 0; i < data.length; i++) {
+            double sum = 0;
+            int count = 0;
+            for (int j = Math.max(0, i - windowSize / 2); j <= Math.min(data.length - 1, i + windowSize / 2); j++) {
+                sum += data[j];
+                count++;
+            }
+            smoothedData[i] = sum / count;
+        }
+        return smoothedData;
+    }
+    //指数平滑
+    private static double[] exponentialSmoothing(double[] data, double alpha) {
+        double[] smoothedData = new double[data.length];
+        smoothedData[0] = data[0]; // 初始化第一个值
+        for (int i = 1; i < data.length; i++) {
+            smoothedData[i] = alpha * data[i] + (1 - alpha) * smoothedData[i - 1];
+        }
+        return smoothedData;
+    }
+
+    private static double queryOriginalValue(LocalDateTime dateTime) {
+        // Simulate querying the database for the original value
+        // Replace with actual database query
+        return 100.0; // Placeholder value
+    }
+
+    private static Map<String, Object> filterMap(Map<String, Object> map, String... keys) {
+        Map<String, Object> filteredMap = new LinkedHashMap<>();
+        for (String key : keys) {
+            if (map.containsKey(key)) {
+                filteredMap.put(key, map.get(key));
+            }
+        }
+        return filteredMap;
+    }
+    private static Map<String, List<String>> parseConfig(String configstr) {
+        // Initialize the map to hold the parsed configuration
+        Map<String, List<String>> configMap = new HashMap<>();
+
+        // Get the configuration string
+        String configString = configstr;
+
+        if (configString != null) {
+            // Split the configuration by different locations
+            String[] locations = configString.split("},");
+
+            for (String location : locations) {
+                // Find the index of the opening brace
+                int braceIndex = location.indexOf('{');
+
+                if (braceIndex > 0) {
+                    // Extract the location name
+                    String locationName = location.substring(0,braceIndex).trim();
+
+                    // Extract the tags and split by comma
+                    String tagsString = location.substring(braceIndex + 1).replace("}", "").trim();
+                    List<String> tags = Arrays.asList(tagsString.split(","));
+
+                    // Add to the map
+                    configMap.put(locationName, tags);
+                }
+            }
+        }
+
+        return configMap;
+    }
+    //TODO 小时营业所片区用水量(自供+(供入-供出))
+    //TODO beforHour是小时数,当前时间往前扣多少个小时 按15分钟刻度计算用水量
+    public static void checkBusinessRecordAllData(int beforHour,String selfconfessStr,String supplyinStr,String confessStr){
+        //TODO 检查小时用水量
+        DateTimeFormatter formater = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        try{
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"检查机制-计算营业所小时用水量开始时间:"+TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT));
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"检查机制-计算营业所小时用水量进行中:......");
+            //获取配置关系
+            //TODO 自供
+            Map<String,List<String>> selfconfess = parseConfig(selfconfessStr);
+            //TODO 供入
+            Map<String,List<String>> supplyin = parseConfig(supplyinStr);
+            //TODO 供出
+            Map<String,List<String>> confess = parseConfig(confessStr);
+            //TODO 根据当前配置信息item 查询远通数据中的历史数据
+            //TODO 首先查询当前水厂设备的从昨天之后到得到数据的数据
+            LocalDateTime today = LocalDateTime.now();
+            LocalDateTime startDateTime = today.withMinute(0).withSecond(0).withNano(0).minusHours(beforHour);
+
+            //TODO 需计算的循环天数
+
+            //TODO 此循环天数每一天所查的是所有设备每小时数据合
+            LocalDateTime newStartDateTime = startDateTime;
+            String startDate = newStartDateTime.format(formater);
+            String endDate = today.withMinute(1).withSecond(0).format(formater);
+            final CountDownLatch latch = new CountDownLatch(selfconfess.keySet().size());
+            for (String orgName:selfconfess.keySet()) {
+                try {
+                    ThreadTaskMgr.runTask(new TraceRunnable(TraceLogMgr.getTraceId()) {
+                        @Override
+                        public void function() {
+
+                            for (int i = 0; i < Integer.valueOf(String.valueOf(Duration.between(startDateTime, today.withSecond(0)).toMinutes() / 15)); i++) {
+                                String startTime = newStartDateTime.minusMinutes(-(i * 15)).format(formater);
+                                String endTime = newStartDateTime.minusMinutes(-1).minusMinutes(-((i + 1) * 15)).format(formater);//查询时间加一分钟
+                                Map<String, Object> recordAllEntity = new HashMap<>();//需要添加的实体数据
+                                recordAllEntity.put("org_name", orgName);//水厂
+                                recordAllEntity.put("time", newStartDateTime.minusMinutes(-((i + 1) * 15)).format(formater));//采集时间(小时的最后时间)
+                                recordAllEntity.put("value", null);
+                                recordAllEntity.put("value_tag", "water");
+                                recordAllEntity.put("collcation_tag_array", "");
+                                //TODO 此循环计算该小时所有设备的用水量
+                                //TODO 先查各个营业所的自供值
+                                List<String> tagTags = selfconfess.get(orgName);//自供
+                                List<String> tagTags2 = supplyin.get(orgName);//供入
+                                List<String> tagTags3 = confess.get(orgName);//供出
+                                Double selfValue = null;
+                                Double supplyInValue = null;
+                                Double confessValue = null;
+                                try {
+                                    selfValue = selfconfess(tagTags, startDate, endDate, startTime, endTime);//自供
+                                    supplyInValue = selfconfess(tagTags2, startDate, endDate, startTime, endTime);//供入
+                                    confessValue = selfconfess(tagTags3, startDate, endDate, startTime, endTime);//供出
+                                } catch (Exception ex) {
+
+                                }
+                                Double value = null;//总计算值
+                                if (selfValue != null) {
+                                    if (supplyInValue != null && confessValue == null) {
+                                        value = selfValue + supplyInValue;
+                                    } else if (supplyInValue != null && confessValue != null) {
+                                        value = selfValue + supplyInValue - confessValue;
+                                    } else if (supplyInValue == null && confessValue == null) {
+                                        value = selfValue;
+                                    } else if (supplyInValue == null && confessValue != null) {
+                                        value = selfValue - confessValue;
+                                    }
+                                }
+                                recordAllEntity.put("value", value);
+                                System.out.println("营业所片区" + orgName + "值:" + value + ",采集时间:" + newStartDateTime.minusMinutes(-((i + 1) * 15)).format(formater));
+                                List<Map<String, Object>> queryWaterRecord = getWaterTapWaterApi().getWaterCollectionRecordAllListNew(1, 0,
+                                        " WHERE org_name = '" + recordAllEntity.get("org_name")
+                                                + "' AND time = '" + recordAllEntity.get("time") + "' AND value_tag = '" + recordAllEntity.get("value_tag") + "'");
+                                if (CollectionUtils.isEmpty(queryWaterRecord)) {
+//                        //TODO 说明不存在,进行插入
+                                    if (!ObjectUtils.isEmpty(recordAllEntity.get("value"))) {
+                                        int insertCode = getWaterTapWaterApi().insertWaterCollectionRecordAllNew(" (" +
+                                                "'" + recordAllEntity.get("org_name") + "'," +
+                                                "'" + recordAllEntity.get("time") + "'," +
+                                                "'" + recordAllEntity.get("value") + "'," +
+                                                "'" + recordAllEntity.get("value_tag") + "'," +
+                                                "'" + recordAllEntity.get("collcation_tag_array") + "'" +
+                                                ") ");
+                                        if (insertCode < 0) {
+                                            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR
+                                                    , mStrClassName
+                                                    , mStrClassName
+                                                    , String.format("Batch initTapWaterDataThread 未成功:{%s} ",
+                                                            FastJsonUtil.toJSON(recordAllEntity)));
+                                        }
+                                    }
+                                } else {
+                                    //TODO 说明存在,进行修改
+                                    if (!ObjectUtils.isEmpty(recordAllEntity.get("value"))) {
+                                        int updateCode = getWaterTapWaterApi().updateWaterCollectionRecordAllNew(String.valueOf(value), " WHERE " +
+                                                "(" +
+                                                " org_name = '" + recordAllEntity.get("org_name") + "' and" +
+                                                " \"time\" = '" + recordAllEntity.get("time") + "' and" +
+                                                " value_tag = '" + recordAllEntity.get("value_tag") + "'" +
+                                                ") ");
+                                        if (updateCode < 0) {
+                                            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR
+                                                    , mStrClassName
+                                                    , mStrClassName
+                                                    , String.format("Batch updateWaterCollectionRecordAll 未成功:{%s} ",
+                                                            FastJsonUtil.toJSON(recordAllEntity)));
+                                        }
+                                    }
+                                }
+                            }
+                            latch.countDown();
+                        }
+                    });
+                }catch(Exception ex){
+
+                }
+            }
+            latch.await();
+        }catch(Exception ex){
+            ex.printStackTrace();
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR
+                    , mStrClassName
+                    , mStrClassName
+                    , String.format("Batch checkBusinessRecordAllData ERROR:{%s} "
+                            , ex.getLocalizedMessage()));
+        }
+    }
+    //TODO 计算总值
+    private static Double selfconfess(List<String> tagTags,String startDate,String endDate,String startTime,String endTime) throws Exception{
+        Double value = null;
+        if (tagTags==null){
+            return value;
+        }
+        for (String tagTag : tagTags) {
+            // 定义字符串日期时间的格式
+            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+            // 解析字符串以创建 LocalDateTime 实例
+            LocalDateTime dateTime = LocalDateTime.parse(endTime, formatter);
+            if (dateTime.getHour()==1&&("OPC_SC.HSS.HSS1.AI.LJLL1.F_CV".equals(tagTag) ||
+                    "OPC_SC.HSS.HSS1.AI.LJLL2.F_CV".equals(tagTag) ||
+                    "OPC_SC.HSS.HSS1.AI.LJLL3.F_CV".equals(tagTag))) {
+                Integer itemCount = getWaterTapWaterApi().getTabWaterHistoryCount(
+                        " WHERE TAG_CODE = '" + tagTag + "' " +
+                                " and QCQUISITION_TIME >= to_date('" + startDate + "', 'yyyy-mm-dd hh24:mi:ss')" +
+                                " and QCQUISITION_TIME < to_date('" + endDate + "', 'yyyy-mm-dd hh24:mi:ss')");
+                if(itemCount!=null&&itemCount>0) {
+                    List<Map<String, Object>> tapWaterHistoryList = getWaterTapWaterApi().getPageZILAISHUI_HISTORY2(itemCount, 0,
+                            " AND TAG_CODE = '" + tagTag + "' " +
+                                    " and QCQUISITION_TIME >= to_date('" + startTime + "', 'yyyy-mm-dd hh24:mi:ss')" +
+                                    " and QCQUISITION_TIME < to_date('" + endTime + "', 'yyyy-mm-dd hh24:mi:ss')" +
+                                    " order by QCQUISITION_TIME");
+                    if (!CollectionUtils.isEmpty(tapWaterHistoryList) && tapWaterHistoryList.size() > 1) {
+                        if (value == null) {
+                            value = 0.00;
+                        }
+                        value += tapWaterHistoryList.get((tapWaterHistoryList.size() - 1)).get("VAL") != null ? Double.valueOf(tapWaterHistoryList.get((tapWaterHistoryList.size() - 1)).get("val").toString()) : null;
+                    }
+                }
+            }else {
+                Integer itemCount = getWaterTapWaterApi().getTabWaterHistoryCount(
+                        " WHERE TAG_CODE = '" + tagTag + "' " +
+                                " and QCQUISITION_TIME >= to_date('" + startDate + "', 'yyyy-mm-dd hh24:mi:ss')" +
+                                " and QCQUISITION_TIME < to_date('" + endDate + "', 'yyyy-mm-dd hh24:mi:ss')");
+                if (itemCount != null && itemCount > 0) {
+                    List<Map<String, Object>> tapWaterHistoryList = getWaterTapWaterApi().getPageZILAISHUI_HISTORY2(itemCount, 0,
+                            " AND TAG_CODE = '" + tagTag + "' " +
+                                    " and QCQUISITION_TIME >= to_date('" + startTime + "', 'yyyy-mm-dd hh24:mi:ss')" +
+                                    " and QCQUISITION_TIME < to_date('" + endTime + "', 'yyyy-mm-dd hh24:mi:ss')" +
+                                    " order by QCQUISITION_TIME");
+                    //TODO tapWaterHistoryList此集合为该设备该小时内的数据,取第一条和最后一条的相差值作为用水量
+                    if (!CollectionUtils.isEmpty(tapWaterHistoryList) && tapWaterHistoryList.size() > 1) {
+                        Double firstValue = tapWaterHistoryList.get(0).get("VAL") != null ? Double.valueOf(tapWaterHistoryList.get(0).get("val").toString()) : null;
+                        Double lastValue = tapWaterHistoryList.get((tapWaterHistoryList.size() - 1)).get("VAL") != null ? Double.valueOf(tapWaterHistoryList.get((tapWaterHistoryList.size() - 1)).get("val").toString()) : null;
+                        if (firstValue != null && lastValue != null) {
+                            //到此处是该小时一个设备的用水量已加上
+                            if (value == null) {
+                                value = 0.00;
+                            }
+                            value += Math.abs(lastValue - firstValue);
+                        }
+                    }
+                }
+            }
+        }
+        return value;
+    }
+
+    //TODO 15分钟 分区用水量 每天整点10分检查并写入,检查范围为当前时间到昨天23点
+    public static void checkRecordAllDataBusinessFenqu(int beforHour){
+        //TODO 检查小时用水量
+        DateTimeFormatter formater = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"检查机制-计算15分钟用水量开始时间:"+TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT));
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"检查机制-计算15分钟用水量进行中:......");
+        List<Map<String, Object>> configList = getWaterTapWaterApi().getWaterCollectionConfigList("WHERE 1=1 AND org_name not like '%营业所' AND org_name!='北碚水厂' AND org_name!='渝中区水厂'");
+        if (!CollectionUtils.isEmpty(configList)) {
+            //TODO 按照组织机构分组
+            Map<Object, List<Map<String, Object>>> groupedData =
+                    configList.stream().collect(Collectors.groupingBy(item -> item.get("org_name")));
+            final CountDownLatch latch = new CountDownLatch(groupedData.keySet().size());
+            for (Object key:groupedData.keySet()){
+                try {
+                    ThreadTaskMgr.runTask(new TraceRunnable(TraceLogMgr.getTraceId()) {
+                        @Override
+                        public void function() {
+                            //TODO 根据当前配置信息item 查询远通数据中的历史数据
+                            //TODO 首先查询当前水厂设备的从昨天之后到得到数据的数据
+                            LocalDateTime today = LocalDateTime.now();
+                            LocalDateTime startDateTime = today.withMinute(0).withSecond(0).withNano(0).minusHours(beforHour);
+
+                            //TODO 需计算的循环天数
+
+                            //TODO 此循环天数每一天所查的是所有设备每小时数据合
+                            LocalDateTime newStartDateTime = startDateTime;
+                            String startDate = newStartDateTime.format(formater);
+                            String endDate = today.withMinute(1).withSecond(0).format(formater);
+                            List<Map<String, Object>> deviceList = groupedData.get(key);
+                            //TODO 循环获取该天该水厂每个设备数据
+
+                            //TODO 查询当前天日期内每小时的设备数据
+                            for (int i = 0; i < Integer.valueOf(String.valueOf(Duration.between(startDateTime, today.withSecond(0)).toMinutes()/15)); i++) {
+                                String startTime = newStartDateTime.minusMinutes(-(i * 15)).format(formater);
+                                String endTime = newStartDateTime.minusMinutes(-1).minusMinutes(-((i + 1)*15)).format(formater);//查询时间加一分钟
+                                Map<String, Object> recordAllEntity = new HashMap<>();//需要添加的实体数据
+                                recordAllEntity.put("org_name", key.toString());//水厂
+                                recordAllEntity.put("time", newStartDateTime.minusMinutes(-((i + 1)*15)).format(formater));//采集时间(小时的最后时间)
+                                recordAllEntity.put("value", null);
+                                recordAllEntity.put("value_tag", "water");
+                                recordAllEntity.put("collcation_tag_array", FastJsonUtil.toJSON(deviceList));
+                                Double value = null;
+                                //TODO 此循环计算该小时所有设备的用水量
+                                for (Map<String, Object> item : deviceList) {
+                                    //TODO 和尚山水厂的三个OPC的设备0点到1点的数据特殊处理,直接取最后一条数据作为0点到1点的用水量
+                                    // 定义字符串日期时间的格式
+                                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+                                    // 解析字符串以创建 LocalDateTime 实例
+                                    LocalDateTime dateTime = LocalDateTime.parse(endTime, formatter);
+                                    if (dateTime.getHour()==1&&("OPC_SC.HSS.HSS1.AI.LJLL1.F_CV".equals(item.get("collcation_tag").toString()) ||
+                                            "OPC_SC.HSS.HSS1.AI.LJLL2.F_CV".equals(item.get("collcation_tag").toString()) ||
+                                            "OPC_SC.HSS.HSS1.AI.LJLL3.F_CV".equals(item.get("collcation_tag").toString()))) {
+                                        Integer itemCount = getWaterTapWaterApi().getTabWaterHistoryCount(
+                                                " WHERE TAG_CODE = '" + item.get("collcation_tag") + "' " +
+                                                        " and QCQUISITION_TIME >= to_date('" + startDate + "', 'yyyy-mm-dd hh24:mi:ss')" +
+                                                        " and QCQUISITION_TIME < to_date('" + endDate + "', 'yyyy-mm-dd hh24:mi:ss')");
+                                        if(itemCount!=null&&itemCount>0) {
+                                            List<Map<String, Object>> tapWaterHistoryList = getWaterTapWaterApi().getPageZILAISHUI_HISTORY2(itemCount, 0,
+                                                    " AND TAG_CODE = '" + item.get("collcation_tag") + "' " +
+                                                            " and QCQUISITION_TIME >= to_date('" + startTime + "', 'yyyy-mm-dd hh24:mi:ss')" +
+                                                            " and QCQUISITION_TIME < to_date('" + endTime + "', 'yyyy-mm-dd hh24:mi:ss')" +
+                                                            " order by QCQUISITION_TIME");
+                                            if (!CollectionUtils.isEmpty(tapWaterHistoryList) && tapWaterHistoryList.size() > 1) {
+                                                if (value == null) {
+                                                    value = 0.00;
+                                                }
+                                                value += tapWaterHistoryList.get((tapWaterHistoryList.size() - 1)).get("VAL") != null ? Double.valueOf(tapWaterHistoryList.get((tapWaterHistoryList.size() - 1)).get("val").toString()) : null;
+                                            }
+                                        }
+                                    }else {
+                                        Integer itemCount = getWaterTapWaterApi().getTabWaterHistoryCount(
+                                                " WHERE TAG_CODE = '" + item.get("collcation_tag") + "' " +
+                                                        " and QCQUISITION_TIME >= to_date('" + startDate + "', 'yyyy-mm-dd hh24:mi:ss')" +
+                                                        " and QCQUISITION_TIME < to_date('" + endDate + "', 'yyyy-mm-dd hh24:mi:ss')");
+                                        if (itemCount != null && itemCount > 0) {
+                                            List<Map<String, Object>> tapWaterHistoryList = getWaterTapWaterApi().getPageZILAISHUI_HISTORY2(itemCount, 0,
+                                                    " AND TAG_CODE = '" + item.get("collcation_tag") + "' " +
+                                                            " and QCQUISITION_TIME >= to_date('" + startTime + "', 'yyyy-mm-dd hh24:mi:ss')" +
+                                                            " and QCQUISITION_TIME < to_date('" + endTime + "', 'yyyy-mm-dd hh24:mi:ss')" +
+                                                            " order by QCQUISITION_TIME");
+                                            //TODO tapWaterHistoryList此集合为该设备该小时内的数据,取第一条和最后一条的相差值作为用水量
+                                            if (!CollectionUtils.isEmpty(tapWaterHistoryList) && tapWaterHistoryList.size() > 1) {
+                                                Double firstValue = tapWaterHistoryList.get(0).get("VAL") != null ? Double.valueOf(tapWaterHistoryList.get(0).get("val").toString()) : null;
+                                                Double lastValue = tapWaterHistoryList.get((tapWaterHistoryList.size() - 1)).get("VAL") != null ? Double.valueOf(tapWaterHistoryList.get((tapWaterHistoryList.size() - 1)).get("val").toString()) : null;
+                                                if (firstValue != null && lastValue != null) {
+                                                    //到此处是该小时一个设备的用水量已加上
+                                                    if (value == null) {
+                                                        value = 0.00;
+                                                    }
+                                                    value += Math.abs(lastValue - firstValue);
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                                recordAllEntity.put("value", value);
+                                List<Map<String, Object>> queryWaterRecord = getWaterTapWaterApi().getWaterCollectionRecordAllListNew(1, 0,
+                                        " WHERE org_name = '" + recordAllEntity.get("org_name")
+                                                + "' AND time = '" + recordAllEntity.get("time") + "' AND value_tag = '" + recordAllEntity.get("value_tag") + "'");
+                                if (CollectionUtils.isEmpty(queryWaterRecord)) {
+                                    //TODO 说明不存在,进行插入
+                                    if(!ObjectUtils.isEmpty(recordAllEntity.get("value"))) {
+                                        int insertCode = getWaterTapWaterApi().insertWaterCollectionRecordAllNew(" (" +
+                                                "'" + recordAllEntity.get("org_name") + "'," +
+                                                "'" + recordAllEntity.get("time") + "'," +
+                                                "'" + recordAllEntity.get("value") + "'," +
+                                                "'" + recordAllEntity.get("value_tag") + "'," +
+                                                "'" + recordAllEntity.get("collcation_tag_array") + "'" +
+                                                ") ");
+                                        if (insertCode < 0) {
+                                            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR
+                                                    , mStrClassName
+                                                    , mStrClassName
+                                                    , String.format("Batch initTapWaterDataThread 未成功:{%s} ",
+                                                            FastJsonUtil.toJSON(recordAllEntity)));
+                                        }
+                                    }
+                                }else{
+                                    //TODO 说明存在,进行修改
+                                    if(!ObjectUtils.isEmpty(recordAllEntity.get("value"))) {
+                                        int updateCode = getWaterTapWaterApi().updateWaterCollectionRecordAllNew(String.valueOf(value)," WHERE " +
+                                                "(" +
+                                                " org_name = '" + recordAllEntity.get("org_name") + "' and" +
+                                                " \"time\" = '" + recordAllEntity.get("time") + "' and" +
+                                                " value_tag = '" + recordAllEntity.get("value_tag") + "'" +
+                                                ") ");
+                                        if (updateCode < 0) {
+                                            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR
+                                                    , mStrClassName
+                                                    , mStrClassName
+                                                    , String.format("Batch updateWaterCollectionRecordAll 未成功:{%s} ",
+                                                            FastJsonUtil.toJSON(recordAllEntity)));
+                                        }
+                                    }
+                                }
+                            }
+                            latch.countDown();
+                        }
+                    });
+                }catch(Exception ex){}
+            }
+            try{latch.await();}catch(Exception ex){}
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"检查机制-计算15分钟用水量结束时间:"+TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT));
+        }
+    }
 
     //TODO 小时用水量 每天整点10分检查并写入,检查范围为当前时间到昨天23点
     public static void checkRecordAllData(int beforHour){
@@ -45,7 +602,7 @@ public class KprAimTapWaterBizFun {
 
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"检查机制-计算小时用水量开始时间:"+TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT));
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"检查机制-计算小时用水量进行中:......");
-        List<Map<String, Object>> configList = getWaterTapWaterApi().getWaterCollectionConfigList(null);
+        List<Map<String, Object>> configList = getWaterTapWaterApi().getWaterCollectionConfigList("WHERE 1=1 AND org_name not like '%营业所' AND org_name!='北碚水厂' AND org_name!='渝中区水厂'");
         if (!CollectionUtils.isEmpty(configList)) {
             //TODO 按照组织机构分组
             Map<Object, List<Map<String, Object>>> groupedData =
@@ -71,7 +628,7 @@ public class KprAimTapWaterBizFun {
                             //TODO 循环获取该天该水厂每个设备数据
 
                             //TODO 查询当前天日期内每小时的设备数据
-                            for (int i = 0; i < Integer.valueOf(String.valueOf(Duration.between(startDateTime, today.withMinute(0).withSecond(0)).toHours())); i++) {
+                            for (int i = 0; i < Integer.valueOf(String.valueOf(Duration.between(startDateTime, today.withSecond(0)).toMinutes()/15)); i++) {
                                 String startTime = newStartDateTime.minusHours(-i).format(formater);
                                 String endTime = newStartDateTime.minusMinutes(-1).minusHours(-(i+1)).format(formater);//查询时间加一分钟
                                 Map<String, Object> recordAllEntity = new HashMap<>();//需要添加的实体数据
@@ -189,7 +746,7 @@ public class KprAimTapWaterBizFun {
     public static void checkRecordData(){
 //TODO ① 首先查询水厂设备配置信息
         try {
-            List<Map<String, Object>> configList = getWaterTapWaterApi().getWaterCollectionConfigList(null);
+            List<Map<String, Object>> configList = getWaterTapWaterApi().getWaterCollectionConfigList("WHERE 1=1 AND org_name not like '%营业所' AND org_name!='北碚水厂' AND org_name!='渝中区水厂'");
             if(!CollectionUtils.isEmpty(configList)){
                 //声明总数据的数据数组
                 List<Map<String,Object>> newRecordAll = Collections.synchronizedList(new LinkedList<Map<String,Object>>());
@@ -283,7 +840,7 @@ public class KprAimTapWaterBizFun {
     public static void initTapWaterData(){
         //TODO ① 首先查询水厂设备配置信息
         try {
-            List<Map<String, Object>> configList = getWaterTapWaterApi().getWaterCollectionConfigList(null);
+            List<Map<String, Object>> configList = getWaterTapWaterApi().getWaterCollectionConfigList("WHERE 1=1 AND org_name not like '%营业所' AND org_name!='北碚水厂' AND org_name!='渝中区水厂'");
             if(!CollectionUtils.isEmpty(configList)){
                 //声明总数据的数据数组
                 List<Map<String,Object>> newRecordAll = Collections.synchronizedList(new LinkedList<Map<String,Object>>());
@@ -376,7 +933,7 @@ public class KprAimTapWaterBizFun {
 
             LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"计算小时用水量开始时间:"+TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT));
             LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"计算小时用水量进行中:......");
-            List<Map<String, Object>> configList = getWaterTapWaterApi().getWaterCollectionConfigList(null);
+            List<Map<String, Object>> configList = getWaterTapWaterApi().getWaterCollectionConfigList("WHERE 1=1 AND org_name not like '%营业所' AND org_name!='北碚水厂' AND org_name!='渝中区水厂'");
             if (!CollectionUtils.isEmpty(configList)) {
                 //TODO 按照组织机构分组
                 Map<Object, List<Map<String, Object>>> groupedData =
@@ -415,14 +972,14 @@ public class KprAimTapWaterBizFun {
 
                                                 //TODO 循环获取该天该水厂每个设备数据
 
-                                                //TODO 查询当前天日期内每小时的设备数据
-                                                for (int i = 0; i < 24; i++) {
-                                                    String startTime = newStartDateTime.withHour(i).format(formater);
-                                                    String endTime = newStartDateTime.withHour(i).minusMinutes(-1).minusHours(-1).format(formater);//查询时间加一分钟
+                                                //TODO 查询当前天日期内每15分钟的设备数据
+                                                for (int i = 0; i < 96; i++) {
+                                                    String startTime = newStartDateTime.minusHours(-i).format(formater);
+                                                    String endTime = newStartDateTime.minusMinutes(-1).minusHours(-(i+1)).format(formater);//查询时间加一分钟
 
                                                     Map<String, Object> recordAllEntity = new HashMap<>();//需要添加的实体数据
                                                     recordAllEntity.put("org_name", key.toString());//水厂
-                                                    recordAllEntity.put("time", newStartDateTime.withHour(i).minusHours(-1).format(formater));//采集时间(小时的最后时间)
+                                                    recordAllEntity.put("time", newStartDateTime.minusHours(-(i+1)).format(formater));//采集时间(小时的最后时间)
                                                     recordAllEntity.put("value", null);
                                                     recordAllEntity.put("value_tag", "water");
                                                     recordAllEntity.put("collcation_tag_array", FastJsonUtil.toJSON(deviceList));

+ 262 - 1
src/main/java/com/shkpr/service/aimodelpower/bizmgr/KprAimWaterCollecationBizFun.java

@@ -506,6 +506,119 @@ public class KprAimWaterCollecationBizFun {
         }
     }
 
+    //TODO 获取15分钟实际水量数据
+    public static ResponseRes selectRealMinutesWaterList(JPRealHourWater jpTbMHourWater,Integer level,Map<String, Map<String, List<String>>> result
+            ,Map<String,String> workZonIds){
+        ResponseRes responseRes = new ResponseRes();
+        List<Map<String, Object>> list = new ArrayList<>();
+        Map<String, Object> map = new HashMap<>();
+//        map.put("id", null);
+        map.put("org_name", null);
+        map.put("time", null);
+        map.put("value", null);
+//        map.put("value_tag", null);
+//        map.put("collcation_tag_array", null);
+        list.add(map);
+        responseRes.setResdata(list);
+        responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
+        responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg());
+        try {
+            List<Map<String, Object>> orgConfig = getWaterTapWaterApi().getOrgConfig(false, 0, 0, " AND org_name not like '%水厂'");
+            if ("water_volume_prediction_jiangjin2".equals(databaseName)) {
+                orgConfig = getWaterTapWaterApi().getOrgConfig(false, 0, 0, "");
+            }
+            if(!CollectionUtils.isEmpty(orgConfig)){
+                //TODO 根据分区编号找到对应的名称
+                if(level==null||level!=1) {
+                    Optional<Map<String, Object>> mapOrg = orgConfig.stream()
+                            .filter(maps -> jpTbMHourWater.getOrgId().equals(maps.get("org_id")))
+                            .findFirst();
+                    if (mapOrg.isPresent()) {
+                        Map<String, Object> currentOrg = mapOrg.get();
+                        List<Map<String, Object>> recordAllRes = getWaterTapApi()
+                                .getWaterCollectionRecordAllListAllNew(" WHERE 1=1 " +
+                                        " AND org_name = '" + currentOrg.get("org_name").toString() + "'" +
+                                        jpTbMHourWater.getForDateStr());
+                        recordAllRes.stream()
+                                .forEach(item -> {
+                                    item.remove("id");
+                                    item.remove("value_tag");
+                                    item.remove("collcation_tag_array");
+                                });
+                        if (jpTbMHourWater.getDayData()) {
+                            responseRes.setResdata(aggregateByDay(recordAllRes));
+                        } else {
+                            responseRes.setResdata(recordAllRes);
+                        }
+                    }
+                }else if(level!=null&&level ==1){
+                    //TODO 一级已经没有数据了(水厂), 查询一级的话则是将其下的供水数据相加
+                    //TODO 查询二级,及其二级带的三级
+                    List<String> childList = new ArrayList<>();//要查询的组织机构名称集合
+                    List<String> childIdList = new ArrayList<>();//要查询的组织机构id集合
+                    Optional zoneNameOpt = findOrgNameByOrgId(workZonIds,jpTbMHourWater.getOrgId());
+                    if(zoneNameOpt.isPresent()){
+                        String zoneName = zoneNameOpt.get().toString();
+                        Map<String, List<String>> childMap = result.get(zoneName);//二级
+                        Collection<List<String>> child2Map = childMap.values();//三级
+                        // 添加二级组织机构名称(childMap 的 keySet)
+                        childList.addAll(childMap.keySet());
+                        // 添加三级组织机构名称(child2Map 的所有 List<String>)
+                        for (List<String> child2List : child2Map) {
+                            childList.addAll(child2List);
+                        }
+                    }
+                    // 结果集合,存储 childList 对应的组织机构 ID
+                    // 遍历 childList,从 workZonIds 中获取对应的 ID
+                    for (String orgName : childList) {
+                        String orgId = workZonIds.get(orgName);
+                        if (orgId != null) { // 避免空值
+                            childIdList.add(orgId);
+                        }
+                    }
+                    List<Map<String,Object>> newResList = new ArrayList<>();
+                    int index = 0;
+                    for (String orgName:childList){
+                        List<Map<String,Object>> resList = getWaterTapApi()
+                                .getWaterCollectionRecordAllListAllNew(" WHERE 1=1 " +
+                                        " AND org_name = '"+orgName+"'" +
+                                        jpTbMHourWater.getForDateStr() + " ORDER BY time ASC ");
+                        if(!CollectionUtils.isEmpty(newResList)&&!CollectionUtils.isEmpty(resList)){
+                            //TODO 说明要查询的分区不止一个,则&把原来有的数据与新查的数据相加,因为按Date排了序所以一致
+                            for (int i=0;i<newResList.size();i++){
+                                newResList.get(i).put("value",
+                                        String.valueOf(parseDouble(newResList.get(i).get("value")) +
+                                                parseDouble(resList.get(i).get("value"))));
+                                newResList.get(i).put("org_name",orgName);
+                                newResList.get(i).put("time",resList.get(i).get("time"));
+                            }
+                        }else {
+                            newResList.addAll(resList);
+                        }
+                        index++;
+                    }
+                    newResList.stream()
+                            .forEach(item -> {
+                                item.remove("id");
+                                item.remove("value_tag");
+                                item.remove("collcation_tag_array");
+                            });
+                    if(jpTbMHourWater.getDayData()){
+                        responseRes.setResdata(aggregateByDay(newResList));
+                    }else{
+                        responseRes.setResdata(newResList);
+                    }
+                }
+            }
+            return responseRes;
+        }catch(Exception ex){
+            responseRes.setResdata(null);
+            responseRes.setResmsg(ResponseCode.RESULT_BAD.toStrMsg());
+            responseRes.setRescode(ResponseCode.RESULT_BAD.toStrCode());
+            return responseRes;
+        }
+    }
+
     //TODO 获取小时实际水量数据
     public static ResponseRes selectRealHourWaterList(JPRealHourWater jpTbMHourWater,Integer level,Map<String, Map<String, List<String>>> result
             ,Map<String,String> workZonIds){
@@ -664,7 +777,155 @@ public class KprAimWaterCollecationBizFun {
         return dailyData;
     }
 
-    //TODO 小时取水量预测接口
+    //TODO 15分钟水量预测接口
+    /**
+     * 传入水厂id及日期,返回指定日期内的小时取水量预测数据和实际小时取水量数据
+     */
+    public static ResponseRes selectTbMinutesWaterList(JPTbMMinutesWater jpTbMHourWater,Integer level,Map<String, Map<String, List<String>>> result
+            ,Map<String,String> workZonIds){
+        ResponseRes responseRes = new ResponseRes();
+        List<Map<String, Object>> list = new ArrayList<>();
+        Map<String, Object> map = new HashMap<>();
+        map.put("ID", null);
+        map.put("Date", null);
+        map.put("Hour", null);
+        map.put("HourForecastWaterWithdrawals", null);
+        map.put("HourForecastActualWaterSupply", null);
+        map.put("WaterWithdrawalsEnergy", null);
+        map.put("WaterSupplyEnergy", null);
+        map.put("RealWaterWithdrawalsEnergy", null);
+        map.put("RealWaterSupplyEnergy", null);
+        map.put("LastModifyTime", null);
+        map.put("HourActualWaterWithdrawals", null);
+        map.put("HourActualWaterSupply ", null);
+        list.add(map);
+        responseRes.setResdata(list);
+        responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
+        responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg());
+        try {
+            if ("water_volume_prediction".equals(databaseName)){
+//TODO 自来水分了二级泵房,要做查询数据处理,点击水厂查询条件时,查询其下的泵房数据 再相加,
+                //TODO 点击泵房则就查泵房的数据 ,无需做处理
+                List<String> childList = new ArrayList<>();//要查询的组织机构名称集合
+                List<String> childIdList = new ArrayList<>();//要查询的组织机构id集合
+                if (level==1){
+                    //TODO 一级已经没有数据了(水厂), 查询一级的话则是将其下的供水数据相加
+                    //TODO 查询二级,及其二级带的三级
+                    Optional zoneNameOpt = findOrgNameByOrgId(workZonIds,jpTbMHourWater.getOrgId());
+                    if(zoneNameOpt.isPresent()){
+                        String zoneName = zoneNameOpt.get().toString();
+                        Map<String, List<String>> childMap = result.get(zoneName);//二级
+                        Collection<List<String>> child2Map = childMap.values();//三级
+                        // 添加二级组织机构名称(childMap 的 keySet)
+                        childList.addAll(childMap.keySet());
+                        // 添加三级组织机构名称(child2Map 的所有 List<String>)
+                        for (List<String> child2List : child2Map) {
+                            childList.addAll(child2List);
+                        }
+                    }
+                }else if(level==2){
+                    //TODO 如果是二级,就查询其自身,看看其下还有没有集合,有的话就查其下的所有集合,没有的话就查其自身
+                    Optional zoneNameOpt = findOrgNameByOrgId(workZonIds,jpTbMHourWater.getOrgId());
+                    if(zoneNameOpt.isPresent()) {
+                        String zoneName = zoneNameOpt.get().toString();
+                        List<String> childMap = new ArrayList<>();//三级
+                        // 遍历第一级 Map
+                        for (Map.Entry<String, Map<String, List<String>>> entry : result.entrySet()) {
+                            Map<String, List<String>> nestedMap = entry.getValue();
+                            // 检查第二级键
+                            if (nestedMap.containsKey(zoneName)) {
+                                childMap = nestedMap.get(zoneName);
+                            }
+                        }
+                        if(childMap.size()>0) {
+                            // 添三级组织机构名称(childMap 的 keySet)
+                            childList.addAll(childMap);
+                        }else{
+                            childList.add(zoneName);
+                        }
+                    }
+                }else if(level==3){
+                    //TODO 如果是三级,就查询其自身
+                    Optional zoneNameOpt = findOrgNameByOrgId(workZonIds,jpTbMHourWater.getOrgId());
+                    if(zoneNameOpt.isPresent()) {
+                        String zoneName = zoneNameOpt.get().toString();
+                        childList.add(zoneName);
+                    }
+                }
+                //TODO 开始查询
+                // 结果集合,存储 childList 对应的组织机构 ID
+                // 遍历 childList,从 workZonIds 中获取对应的 ID
+                for (String orgName : childList) {
+                    String orgId = workZonIds.get(orgName);
+                    if (orgId != null) { // 避免空值
+                        childIdList.add(orgId);
+                    }
+                }
+                List<Map<String,Object>> newResList = new ArrayList<>();
+                int index = 0;
+                for (String orgId:childIdList){
+                    jpTbMHourWater.setOrgId(orgId);
+                    jpTbMHourWater.checkValid();
+                    List<Map<String, Object>> resList = getWaterTapWaterApi().getTbMHourwaterNew(jpTbMHourWater.getIsPage(),
+                            jpTbMHourWater.getLimit(), jpTbMHourWater.getOffset(), jpTbMHourWater.getForDateStr()+ " ORDER BY \"Date\",\"Hour\" ASC ");
+                    if(!CollectionUtils.isEmpty(newResList)&&!CollectionUtils.isEmpty(resList)){
+                        //TODO 说明要查询的分区不止一个,则&把原来有的数据与新查的数据相加,因为按Date排了序所以一致
+                        for (int i=0;i<newResList.size();i++){
+                            newResList.get(i).put("HourForecastWaterWithdrawals",
+                                    parseDouble(newResList.get(i).get("HourForecastWaterWithdrawals")) +
+                                            parseDouble(resList.get(i).get("HourForecastWaterWithdrawals")));
+                            newResList.get(i).put("HourForecastActualWaterSupply",
+                                    parseDouble(newResList.get(i).get("HourForecastActualWaterSupply")) +
+                                            parseDouble(resList.get(i).get("HourForecastActualWaterSupply")));
+                            newResList.get(i).put("WaterWithdrawalsEnergy",
+                                    parseDouble(newResList.get(i).get("WaterWithdrawalsEnergy")) +
+                                            parseDouble(resList.get(i).get("WaterWithdrawalsEnergy")));
+                            newResList.get(i).put("WaterSupplyEnergy",
+                                    parseDouble(newResList.get(i).get("WaterSupplyEnergy")) +
+                                            parseDouble(resList.get(i).get("WaterSupplyEnergy")));
+                            newResList.get(i).put("RealWaterWithdrawalsEnergy",
+                                    parseDouble(newResList.get(i).get("RealWaterWithdrawalsEnergy")) +
+                                            parseDouble(resList.get(i).get("RealWaterWithdrawalsEnergy")));
+                            newResList.get(i).put("RealWaterSupplyEnergy",
+                                    parseDouble(newResList.get(i).get("RealWaterSupplyEnergy")) +
+                                            parseDouble(resList.get(i).get("RealWaterSupplyEnergy")));
+                            newResList.get(i).put("HourActualWaterWithdrawals",
+                                    parseDouble(newResList.get(i).get("HourActualWaterWithdrawals")) +
+                                            parseDouble(resList.get(i).get("HourActualWaterWithdrawals")));
+                            newResList.get(i).put("HourActualWaterSupply",
+                                    parseDouble(newResList.get(i).get("HourActualWaterSupply")) +
+                                            parseDouble(resList.get(i).get("HourActualWaterSupply")));
+                        }
+                    }else {
+                        newResList.addAll(resList);
+                    }
+                    index++;
+                }
+                if (!CollectionUtils.isEmpty(newResList)) {
+                    responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
+                    responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg());
+                    responseRes.setResdata(newResList);
+                }
+            }else {
+                //
+                List<Map<String, Object>> resList = getWaterTapWaterApi().getTbMHourwater(jpTbMHourWater.getIsPage(),
+                        jpTbMHourWater.getLimit(), jpTbMHourWater.getOffset(), jpTbMHourWater.getForDateStr());
+                if (!CollectionUtils.isEmpty(resList)) {
+                    responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
+                    responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg());
+                    responseRes.setResdata(resList);
+                }
+            }
+            return responseRes;
+        }catch(Exception ex){
+            responseRes.setResdata(null);
+            responseRes.setResmsg(ResponseCode.RESULT_BAD.toStrMsg());
+            responseRes.setRescode(ResponseCode.RESULT_BAD.toStrCode());
+            return responseRes;
+        }
+    }
+
+    //TODO 小时水量预测接口
     /**
      * 传入水厂id及日期,返回指定日期内的小时取水量预测数据和实际小时取水量数据
      */

+ 2 - 0
src/main/java/com/shkpr/service/aimodelpower/constants/ApiURI.java

@@ -120,7 +120,9 @@ public class ApiURI {
     public static final String URI_WATER_ZILAISHUI_H = URI_CURRENCY_H+"/water/zilaishui";
     public static final String URI_WATER_ZILAISHUI_DAY = "daydata";
     public static final String URI_WATER_ZILAISHUI_HOUR = "hourdata";
+    public static final String URI_WATER_ZILAISHUI_MINUTE = "minutedata";
     public static final String URI_WATER_ZILAISHUI_REAL_HOUR = "realhourdata";
+    public static final String URI_WATER_ZILAISHUI_REAL_MINUTE = "realminutedata";
     public static final String URI_WATER_ZILAISHUI_HOUR_PUMP_IN = "hourIndata";
     public static final String URI_WATER_ZILAISHUI_HOUR_PUMP_OUT= "hourOutdata";
     public static final String URI_WATER_ZILAISHUI_HOUR_LEVEL = "hourleveldata";

+ 134 - 4
src/main/java/com/shkpr/service/aimodelpower/controllerapi/WaterCollecationController.java

@@ -15,10 +15,7 @@ import com.shkpr.service.aimodelpower.dto.ResponseCode;
 import com.shkpr.service.aimodelpower.dto.ResponseRes;
 import com.shkpr.service.aimodelpower.dto.zilaishuiModel.InPumpModel;
 import com.shkpr.service.aimodelpower.exception.SelfException;
-import com.shkpr.service.aimodelpower.jsonbean.zilaishui.JPRealHourWater;
-import com.shkpr.service.aimodelpower.jsonbean.zilaishui.JPTbLevelHourWater;
-import com.shkpr.service.aimodelpower.jsonbean.zilaishui.JPTbMHourWater;
-import com.shkpr.service.aimodelpower.jsonbean.zilaishui.JPTbMWater;
+import com.shkpr.service.aimodelpower.jsonbean.zilaishui.*;
 import org.apache.commons.collections.MapUtils;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -278,6 +275,72 @@ public class WaterCollecationController {
      * @Param
      * @return
      **/
+    @PostMapping(value = ApiURI.URI_WATER_ZILAISHUI_REAL_MINUTE)
+    public ResponseRes realMinutesData(HttpServletRequest request
+            , @RequestHeader(value= ApiURI.HEADER_CLIENT_TYPE, required=false) String strClientType
+            , @RequestHeader(value= ApiURI.HEADER_USER_AGENT, required=false) String strUserAgent) throws Exception{
+        final String URI_PATH = request.getRequestURI();
+        final String strPlatform = CommTool.getPlatformByAgent(strClientType, strUserAgent);
+        final String strUserId = (String)request.getAttribute(TokenAuthenticationService.HEADER_USERID);
+        JPRealHourWater oJsonParam = FastJsonUtil.fromJSONByGson(HttpTool.getJsonBodyStr(request), JPRealHourWater.class);
+        if (oJsonParam == null
+                || !oJsonParam.checkValid()){
+            throw new SelfException(ResponseCode.STATUS_ERROR_JSON_FORMAT.toStrCode()
+                    , String.format(ApiURI.EXCEPTION_FORMAT
+                    , strPlatform
+                    , URI_PATH
+                    , ResponseCode.STATUS_ERROR_JSON_FORMAT.toStrMsg()));
+        }
+        long llReqBefore = System.currentTimeMillis();
+        String strRunSeq = String.format("%d-%d", llReqBefore, mSeqNotify.incrementAndGet());
+
+        ResponseRes<String> resResult = new ResponseRes<String>();
+        resResult.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
+        resResult.setResmsg(MSG_SUCCESS);
+        resResult.setResdata("");
+        try {
+            ResponseRes oRes = new ResponseRes();
+            if ("water_volume_prediction".equals(KprAimWaterCollecationBizFun.databaseName)) {
+                Map<String, Map<String, List<String>>> result = getWaterWorks();
+                Map<String, String> workZonIds = getWaterZoneIds();
+                int level = findOrgLevel(result, KprAimWaterCollecationBizFun.findOrgNameByOrgId(workZonIds, oJsonParam.getOrgId()).get().toString());
+                oRes = KprAimWaterCollecationBizFun.selectRealMinutesWaterList(oJsonParam, level, result, workZonIds);
+            }else{
+                oRes = KprAimWaterCollecationBizFun.selectRealMinutesWaterList(oJsonParam, null,null,null);
+            }
+            if (oRes != null && ResponseCode.RESULT_NORMAL.toStrCode().equals(oRes.getRescode())) {
+                resResult.setResdata(FastJsonUtil.toJSON(oRes.getResdata()));
+            } else {
+                resResult.setRescode(ResponseCode.RESULT_BAD.toStrCode());
+                resResult.setResmsg(MSG_FAILED);
+                resResult.setResdata("");
+            }
+
+            resResult.setTimestamp(System.currentTimeMillis());
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_INTERNAL.toStrValue(), mStrClassName, strUserId
+                    , String.format("%s:%s seq:{%s} rescode:{%s} resmsg:{%s} time:{%d ms} end<===="
+                            , strPlatform
+                            , URI_PATH
+                            , strRunSeq
+                            , resResult.getRescode()
+                            , resResult.getResmsg()
+                            , resResult.getTimestamp() - llReqBefore));
+            return resResult;
+        }catch(Exception ex){
+            resResult.setRescode(ResponseCode.RESULT_BAD.toStrCode());
+            resResult.setResmsg(MSG_FAILED+ex.getLocalizedMessage());
+            resResult.setResdata("");
+            return resResult;
+        }
+    }
+
+    /**
+     * @Author Lx
+     * @Description //TODO 获取实时数据曲线
+     * @Date 14:49 2025/4/24
+     * @Param
+     * @return
+     **/
     @PostMapping(value = ApiURI.URI_WATER_ZILAISHUI_REAL_HOUR)
     public ResponseRes realHourData(HttpServletRequest request
             , @RequestHeader(value= ApiURI.HEADER_CLIENT_TYPE, required=false) String strClientType
@@ -337,6 +400,73 @@ public class WaterCollecationController {
         }
     }
 
+    @PostMapping(value = ApiURI.URI_WATER_ZILAISHUI_MINUTE)
+    public ResponseRes minuteData(HttpServletRequest request
+            , @RequestHeader(value= ApiURI.HEADER_CLIENT_TYPE, required=false) String strClientType
+            , @RequestHeader(value= ApiURI.HEADER_USER_AGENT, required=false) String strUserAgent) throws Exception{
+        final String URI_PATH = request.getRequestURI();
+        final String strPlatform = CommTool.getPlatformByAgent(strClientType, strUserAgent);
+        final String strUserId = (String)request.getAttribute(TokenAuthenticationService.HEADER_USERID);
+        JPTbMMinutesWater oJsonParam = FastJsonUtil.fromJSONByGson(HttpTool.getJsonBodyStr(request), JPTbMMinutesWater.class);
+        if (oJsonParam == null
+                || !oJsonParam.checkValid()){
+            throw new SelfException(ResponseCode.STATUS_ERROR_JSON_FORMAT.toStrCode()
+                    , String.format(ApiURI.EXCEPTION_FORMAT
+                    , strPlatform
+                    , URI_PATH
+                    , ResponseCode.STATUS_ERROR_JSON_FORMAT.toStrMsg()));
+        }
+        long llReqBefore = System.currentTimeMillis();
+        String strRunSeq = String.format("%d-%d", llReqBefore, mSeqNotify.incrementAndGet());
+
+        ResponseRes<String> resResult = new ResponseRes<String>();
+        resResult.setRescode(ResponseCode.RESULT_NORMAL.toStrCode());
+        resResult.setResmsg(MSG_SUCCESS);
+        resResult.setResdata("");
+        try {
+//        resResult.setResdata(waterZILAISHUIDao.getCount("WHERE TAG_CODE = 'SPB.SSWD.total_flow1' and QCQUISITION_TIME >= to_date('2023-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss')").toString());
+            ResponseRes oRes = new ResponseRes();
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_INTERNAL.toStrValue(), mStrClassName, strUserId
+                    , KprAimWaterCollecationBizFun.databaseName);
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_INTERNAL.toStrValue(), mStrClassName, strUserId
+                    , String.valueOf("water_volume_prediction".equals(KprAimWaterCollecationBizFun.databaseName)));
+            if ("water_volume_prediction".equals(KprAimWaterCollecationBizFun.databaseName)) {
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_INTERNAL.toStrValue(), mStrClassName, strUserId
+                        , "1111");
+                //转成集合,最多三级
+                // 最终的三级结构集合
+                Map<String, Map<String, List<String>>> result = getWaterWorks();
+                Map<String, String> workZonIds = getWaterZoneIds();
+                if (!MapUtils.isEmpty(result) && !MapUtils.isEmpty(workZonIds)) {
+                    int level = findOrgLevel(result, KprAimWaterCollecationBizFun.findOrgNameByOrgId(workZonIds, oJsonParam.getOrgId()).get().toString());
+                    oRes = KprAimWaterCollecationBizFun.selectTbMinutesWaterList(oJsonParam, level, result, workZonIds);
+                }
+            }
+            if (oRes != null && ResponseCode.RESULT_NORMAL.toStrCode().equals(oRes.getRescode())) {
+                resResult.setResdata(FastJsonUtil.toJSON(oRes.getResdata()));
+            } else {
+                resResult.setRescode(ResponseCode.RESULT_BAD.toStrCode());
+                resResult.setResmsg(MSG_FAILED);
+                resResult.setResdata("");
+            }
+
+            resResult.setTimestamp(System.currentTimeMillis());
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_INTERNAL.toStrValue(), mStrClassName, strUserId
+                    , String.format("%s:%s seq:{%s} rescode:{%s} resmsg:{%s} time:{%d ms} end<===="
+                            , strPlatform
+                            , URI_PATH
+                            , strRunSeq
+                            , resResult.getRescode()
+                            , resResult.getResmsg()
+                            , resResult.getTimestamp() - llReqBefore));
+            return resResult;
+        }catch(Exception ex){
+            resResult.setRescode(ResponseCode.RESULT_BAD.toStrCode());
+            resResult.setResmsg(MSG_FAILED+ex.getLocalizedMessage());
+            resResult.setResdata("");
+            return resResult;
+        }
+    }
 
     @PostMapping(value = ApiURI.URI_WATER_ZILAISHUI_HOUR)
     public ResponseRes hourData(HttpServletRequest request

+ 2 - 0
src/main/java/com/shkpr/service/aimodelpower/controllerfilter/third/ThirdJWTCurrencyFilter.java

@@ -22,6 +22,8 @@ public class ThirdJWTCurrencyFilter extends JWTAuthenticationFilter {
         msMapURI2Method = new HashMap<String, String>();
         msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_WATER_ZILAISHUI_H, ApiURI.URI_WATER_ZILAISHUI_DAY), "POST");
         msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_WATER_ZILAISHUI_H, ApiURI.URI_WATER_ZILAISHUI_HOUR), "POST");
+        msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_WATER_ZILAISHUI_H, ApiURI.URI_WATER_ZILAISHUI_MINUTE), "POST");
+        msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_WATER_ZILAISHUI_H, ApiURI.URI_WATER_ZILAISHUI_REAL_MINUTE), "POST");
         msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_WATER_ZILAISHUI_H, ApiURI.URI_WATER_ZILAISHUI_REAL_HOUR), "POST");
         msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_WATER_ZILAISHUI_H, ApiURI.URI_WATER_ZILAISHUI_HOUR_PUMP_IN), "POST");
         msMapURI2Method.put(String.format("%s/%s", ApiURI.URI_WATER_ZILAISHUI_H, ApiURI.URI_WATER_ZILAISHUI_HOUR_PUMP_OUT), "POST");

+ 19 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/shizilaishuiDataSource/WaterCollecationDao.java

@@ -68,6 +68,25 @@ public class WaterCollecationDao {
         
     }
 
+    //TODO 查询15分钟水量预测表;支持是否分页
+    public List<Map<String,Object>> getTbMHourwaterNew(boolean isPage,int limit,int offset,String extend){
+        String sql = "";
+        sql = "SELECT " +
+                " a.\"ID\",to_char(a.\"Date\", 'YYYY-MM-DD') AS \"Date\",a.\"Hour\",a.\"HourForecastWaterWithdrawals\",a.\"HourForecastActualWaterSupply\",a.\"WaterWithdrawalsEnergy\",a.\"WaterSupplyEnergy\",a.\"RealWaterWithdrawalsEnergy\",a.\"RealWaterSupplyEnergy\",a.\"LastModifyTime\",a.\"orgId\"," +
+                " a.\"HourActualWaterWithdrawals\",a.\"HourActualWaterSupply\" " +
+                " FROM tb_m_hourwater_new AS a WHERE 1=1 ";
+        if(!StringUtils.isEmpty(extend)){
+            sql+=extend;
+        }
+        if(isPage) {
+            sql += " LIMIT " + limit + " OFFSET " + offset;
+        }
+        JdbcTemplate pgJdbc = new JdbcTemplate(childDataSource);
+        List<Map<String, Object>> tableData = pgJdbc.queryForList(sql);
+        return tableData;
+
+    }
+
     //TODO 查询取水泵房电耗预测接口,支持是否分页
     public List<Map<String,Object>> getTbMHourwaterWaterwithdrawals(boolean isPage,int limit,int offset,String extend){
             String sql = "";

+ 132 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/shizilaishuiDataSource/WaterZILAISHUIDao.java

@@ -142,6 +142,37 @@ public class WaterZILAISHUIDao {
         }
     }
 
+    //TODO 查询市自来水15分钟用水量记录表·分页
+    public List<Map<String,Object>> getWaterCollectionRecordAllListNew(int limit,int offset,String extend){
+        try{
+            String sql = "SELECT * FROM water_collecation_record_all_new ";
+            if(!StringUtils.isEmpty(extend)){
+                sql += extend;
+            }
+            sql += " LIMIT " + limit + " OFFSET "+ offset;
+            JdbcTemplate pgJdbc = new JdbcTemplate(childDataSource);
+            List<Map<String,Object>> tableData = pgJdbc.queryForList(sql);
+            return tableData;
+        }catch(Exception ex){
+            return null;
+        }
+    }
+
+    //TODO 查询市自来水15分钟用水量记录表·不分页
+    public List<Map<String,Object>> getWaterCollectionRecordAllListAllNew(String extend){
+        try{
+            String sql = "SELECT * FROM water_collecation_record_all_new ";
+            if(!StringUtils.isEmpty(extend)){
+                sql += extend;
+            }
+            JdbcTemplate pgJdbc = new JdbcTemplate(childDataSource);
+            List<Map<String,Object>> tableData = pgJdbc.queryForList(sql);
+            return tableData;
+        }catch(Exception ex){
+            return null;
+        }
+    }
+
     //TODO 查询市自来水小时用水量记录表·分页
     public List<Map<String,Object>> getWaterCollectionRecordAllList(int limit,int offset,String extend){
         try{
@@ -172,6 +203,8 @@ public class WaterZILAISHUIDao {
             return null;
         }
     }
+
+
     public List<Map<String,Object>> getPumpCollectionRecordAllListAll(String extend){
         try{
             String sql = "SELECT * FROM water_pump_record_all ";
@@ -203,6 +236,41 @@ public class WaterZILAISHUIDao {
         }
     }
 
+    //TODO 插入自来水15分钟用水量记录表
+    public int insertWaterCollectionRecordAllNew(String extend){
+        try{
+            String sql = "INSERT INTO water_collecation_record_all_new " +
+                    "(org_name,time,value,value_tag,collcation_tag_array) VALUES ";
+            if(StringUtils.isEmpty(extend)){
+                return -1;
+            }
+            sql+=extend;
+            JdbcTemplate pgJdbc = new JdbcTemplate(childDataSource);
+            Integer resCode = pgJdbc.update(sql);
+            return resCode;
+        }catch(Exception ex){
+            return -1;
+        }
+    }
+
+    //TODO 修改自来水15分钟用水量记录表value
+    public int updateWaterCollectionRecordAllNew(String value,String extend){
+        try{
+            String sql = "UPDATE water_collecation_record_all_new " +
+                    " SET \"value\" =  "+value+" " +
+                    " ";
+            if(!StringUtils.isEmpty(extend)){
+                sql = sql +extend;
+            }
+            JdbcTemplate pgJdbc = new JdbcTemplate(childDataSource);
+            Integer resCode = pgJdbc.update(sql);
+            return resCode;
+        }catch(Exception ex){
+            return -1;
+        }
+    }
+
+
     //TODO 插入自来水小时用水量记录表
     public int insertWaterCollectionRecordAll(String extend){
         try{
@@ -414,6 +482,70 @@ public class WaterZILAISHUIDao {
         }
     }
 
+    //TODO 添加或修改15分钟预测数据
+    public int insertOrUpdateTbmHourWaterNew(Map<String,Object> value){
+        try{
+            String sql = "INSERT INTO tb_m_hourwater_new " +
+                    "(\"Date\",\"Hour\"";
+            if(!ObjectUtils.isEmpty(value.get("HourForecastWaterWithdrawals"))){
+                sql +=  " , \"HourForecastWaterWithdrawals\" ";
+            }
+            if(!ObjectUtils.isEmpty(value.get("HourForecastActualWaterSupply"))){
+                sql +=  " ,\"HourForecastActualWaterSupply\"";
+            }
+            if(!ObjectUtils.isEmpty(value.get("HourActualWaterWithdrawals"))){
+                sql +=  " , \"HourActualWaterWithdrawals\"";
+            }
+//            if(!ObjectUtils.isEmpty(value.get("HourActualWaterSupply"))){
+            sql +=  " , \"HourActualWaterSupply\"";
+//            }
+            sql+= ",\"LastModifyTime\",\"orgId\" ) VALUES ";
+            sql +=" ( ";
+            int i = 1;
+            for (Object key : value.keySet()){
+                if(i==value.keySet().size()){
+                    if(ObjectUtils.isEmpty(value.get(key))){
+                        sql += " NULL ";
+                    }else {
+                        sql += "'" + value.get(key) + "'";
+                    }
+                }else {
+                    if(ObjectUtils.isEmpty(value.get(key))) {
+                        sql += " NULL ,";
+                    }else {
+                        sql += "'" + value.get(key) + "',";
+                    }
+                }
+                i++;
+            }
+            sql += " )";
+            sql += " ON CONFLICT (\"Date\",\"orgId\",\"Hour\") " +
+                    " DO UPDATE " +
+                    " SET \"Date\" =  '"+value.get("Date")+"' " +
+                    " , \"Hour\" =  '"+value.get("Hour")+"' ";
+            if(!ObjectUtils.isEmpty(value.get("HourForecastWaterWithdrawals"))){
+                sql +=  " , \"HourForecastWaterWithdrawals\" =  '"+value.get("HourForecastWaterWithdrawals")+"' ";
+            }
+            if(!ObjectUtils.isEmpty(value.get("HourForecastActualWaterSupply"))){
+                sql +=  " ,\"HourForecastActualWaterSupply\" =  '"+value.get("HourForecastActualWaterSupply")+"' ";
+            }
+            if(!ObjectUtils.isEmpty(value.get("HourActualWaterWithdrawals"))){
+                sql +=  " , \"HourActualWaterWithdrawals\" =  '"+value.get("HourActualWaterWithdrawals")+"' ";
+            }
+            if(!ObjectUtils.isEmpty(value.get("HourActualWaterSupply"))){
+                sql +=  " , \"HourActualWaterSupply\" =  '"+value.get("HourActualWaterSupply")+"' ";
+            }
+
+            sql += " , \"LastModifyTime\" =  '"+value.get("LastModifyTime")+"' " +
+                    " , \"orgId\" =  '"+value.get("orgId")+"' ";
+            JdbcTemplate pgJdbc = new JdbcTemplate(childDataSource);
+            Integer resCode = pgJdbc.update(sql);
+            return resCode;
+        }catch(Exception ex){
+            return -1;
+        }
+    }
+
     //TODO 添加或修改日小时开泵预测表
     public int insertOrUpdateTbmHourwaterWatersupply(Map<String,Object> value){
         try{

+ 20 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/shizilaishuiDataSource/service/WaterCollecationServiceImpl.java

@@ -102,6 +102,26 @@ public class WaterCollecationServiceImpl implements WaterCollecationService{
     }
 
     @Override
+    public List<Map<String, Object>> getTbMHourwaterNew(Boolean isPage, int limit, int offset, String extend) throws Exception {
+        int nCode = 0;
+        String strMsg = "Success";
+        List<Map<String, Object>> arrRes = null;
+        try {
+            arrRes = waterCollecationDao.getTbMHourwaterNew(isPage,limit,offset,extend);
+        }catch (Exception e){ throw new Exception(e.getLocalizedMessage());
+
+
+        }finally {
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.valueFromInt(nCode)
+                    , LogFlagBusiType.BUSI_CHILD_DB_TAP_WATER.toStrValue()
+                    , mStrClassName
+                    , String.format("Batch Query TbMWater from database, code:{%d} msg:{%s} ..."
+                            , nCode, strMsg));
+        }
+        return arrRes;
+    }
+
+    @Override
     public List<Map<String, Object>> getTbMHourwaterWaterwithdrawals(boolean isPage, int limit, int offset, String extend) throws Exception{
         int nCode = 0;
         String strMsg = "Success";

+ 103 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/shizilaishuiDataSource/service/WaterTapWaterServiceImpl.java

@@ -309,6 +309,27 @@ public class WaterTapWaterServiceImpl implements WaterTapWaterService {
     }
 
     @Override
+    public Integer insertOrUpdateTbmHourWaterNew(Map<String, Object> value) {
+        int nCode = 0;
+        String strMsg = "Success";
+        Integer arrRes = null;
+        try {
+            arrRes = waterZILAISHUIDao.insertOrUpdateTbmHourWaterNew(value);
+        } catch (Exception e) {
+            nCode = LogLevelFlag.LOG_ERROR.ordinal();
+            strMsg = e.getLocalizedMessage();
+        } finally {
+//            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.valueFromInt(nCode)
+//                    , LogFlagBusiType.BUSI_CHILD_DB_TAP_WATER.toStrValue()
+//                    , mStrClassName
+//                    , String.format("Batch Insert WaterRecord:{%s} from database, code:{%s} msg:{%s} ..."
+//                            , arrRes
+//                            , nCode, strMsg));
+        }
+        return arrRes;
+    }
+
+    @Override
     public Integer insertOrUpdateTbmHourwaterWatersupply(Map<String, Object> value) {
         int nCode = 0;
         String strMsg = "Success";
@@ -358,4 +379,86 @@ public class WaterTapWaterServiceImpl implements WaterTapWaterService {
     public int updateWaterPumpRecordAll(String value, String extend) {
         return waterZILAISHUIDao.updateWaterPumpRecordAll(value, extend);
     }
+
+    @Override
+    public List<Map<String, Object>> getWaterCollectionRecordAllListNew(int limit, int offset, String extend) {
+        int nCode = 0;
+        String strMsg = "Success";
+        List<Map<String, Object>> arrRes = null;
+        try {
+            arrRes = waterZILAISHUIDao.getWaterCollectionRecordAllListNew(limit,offset,extend);
+        }catch (Exception e){
+            nCode = LogLevelFlag.LOG_ERROR.ordinal();
+            strMsg = e.getLocalizedMessage();
+        }finally {
+//            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.valueFromInt(nCode)
+//                    , LogFlagBusiType.BUSI_CHILD_DB_TAP_WATER.toStrValue()
+//                    , mStrClassName
+//                    , String.format("Batch Query TabWaterHistory from database, code:{%d} msg:{%s} ..."
+//                            , nCode, strMsg));
+        }
+        return arrRes;
+    }
+
+    @Override
+    public List<Map<String, Object>> getWaterCollectionRecordAllListAllNew(String extend) {
+        int nCode = 0;
+        String strMsg = "Success";
+        List<Map<String, Object>> arrRes = null;
+        try {
+            arrRes = waterZILAISHUIDao.getWaterCollectionRecordAllListAllNew(extend);
+        }catch (Exception e){
+            nCode = LogLevelFlag.LOG_ERROR.ordinal();
+            strMsg = e.getLocalizedMessage();
+        }finally {
+//            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.valueFromInt(nCode)
+//                    , LogFlagBusiType.BUSI_CHILD_DB_TAP_WATER.toStrValue()
+//                    , mStrClassName
+//                    , String.format("Batch Query TabWaterHistory from database, code:{%d} msg:{%s} ..."
+//                            , nCode, strMsg));
+        }
+        return arrRes;
+    }
+
+    @Override
+    public Integer insertWaterCollectionRecordAllNew(String extend) {
+        int nCode = 0;
+        String strMsg = "Success";
+        Integer arrRes = null;
+        try {
+            arrRes = waterZILAISHUIDao.insertWaterCollectionRecordAllNew(extend);
+        }catch (Exception e){
+            nCode = LogLevelFlag.LOG_ERROR.ordinal();
+            strMsg = e.getLocalizedMessage();
+        }finally {
+//            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.valueFromInt(nCode)
+//                    , LogFlagBusiType.BUSI_CHILD_DB_TAP_WATER.toStrValue()
+//                    , mStrClassName
+//                    , String.format("Batch Insert WaterRecord:{%s} from database, code:{%s} msg:{%s} ..."
+//                            , arrRes
+//                            , nCode, strMsg));
+        }
+        return arrRes;
+    }
+
+    @Override
+    public Integer updateWaterCollectionRecordAllNew(String value, String extend) {
+        int nCode = 0;
+        String strMsg = "Success";
+        Integer arrRes = null;
+        try {
+            arrRes = waterZILAISHUIDao.updateWaterCollectionRecordAllNew(value,extend);
+        }catch (Exception e){
+            nCode = LogLevelFlag.LOG_ERROR.ordinal();
+            strMsg = e.getLocalizedMessage();
+        }finally {
+//            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.valueFromInt(nCode)
+//                    , LogFlagBusiType.BUSI_CHILD_DB_TAP_WATER.toStrValue()
+//                    , mStrClassName
+//                    , String.format("Batch Insert WaterRecord:{%s} from database, code:{%s} msg:{%s} ..."
+//                            , arrRes
+//                            , nCode, strMsg));
+        }
+        return arrRes;
+    }
 }

+ 2 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/shizilaishuiDataSource/service/intef/WaterCollecationService.java

@@ -20,6 +20,8 @@ public interface WaterCollecationService {
 
     //TODO 查询样本及预测水量表;支持是否分页
     public List<Map<String,Object>> getTbMHourwater(Boolean isPage, int limit, int offset, String extend)throws Exception;
+    //TODO 查询15分钟样本及预测水量表;支持是否分页
+    public List<Map<String,Object>> getTbMHourwaterNew(Boolean isPage, int limit, int offset, String extend)throws Exception;
 
     //TODO 查询取水泵房电耗预测接口
     public List<Map<String,Object>> getTbMHourwaterWaterwithdrawals(boolean isPage,int limit,int offset,String extend)throws Exception;

+ 11 - 0
src/main/java/com/shkpr/service/aimodelpower/dbdao/shizilaishuiDataSource/service/intef/WaterTapWaterService.java

@@ -17,6 +17,10 @@ public interface WaterTapWaterService {
     //TODO pgsql 查询市自来水历史记录表·分页
     public List<Map<String,Object>> getWaterCollectionRecordList(int limit,int offset,String extend);
 
+    //TODO pgsql 查询市自来水15分钟用水量记录表·分页
+    public List<Map<String,Object>> getWaterCollectionRecordAllListNew(int limit,int offset,String extend);
+    //TODO pgsql 查询市自来水15分钟用水量记录表·不分页
+    public List<Map<String,Object>> getWaterCollectionRecordAllListAllNew(String extend);
     //TODO pgsql 查询市自来水小时用水量记录表·分页
     public List<Map<String,Object>> getWaterCollectionRecordAllList(int limit,int offset,String extend);
     //TODO pgsql 查询市自来水小时用水量记录表·不分页
@@ -24,6 +28,11 @@ public interface WaterTapWaterService {
     //TODO pgsql 查询市自来水小时泵原始数据记录表·不分页
     public List<Map<String,Object>> getPumpCollectionRecordAllListAll(String extend);
 
+
+    //TODO pgsql 插入自来水15分钟用水量记录表
+    public Integer insertWaterCollectionRecordAllNew(String extend);
+    //TODO pgsql 修改自来水15分钟用水量记录
+    public Integer updateWaterCollectionRecordAllNew(String value,String extend);
     //TODO pgsql 插入自来水历史记录表
     public Integer insertWaterCollectionRecord(String extend);
     //TODO pgsql 插入自来水小时用水量记录表
@@ -39,6 +48,8 @@ public interface WaterTapWaterService {
     public Integer insertOrUpdateTbmWater(Map<String,Object> value);
     //TODO 添加或修改日小时预测数据
     public Integer insertOrUpdateTbmHourWater(Map<String,Object> value);
+    //TODO 添加或修改日15分钟预测数据
+    public Integer insertOrUpdateTbmHourWaterNew(Map<String,Object> value);
     //TODO 添加或修改日小时开泵预测表
     public Integer insertOrUpdateTbmHourwaterWatersupply(Map<String,Object> value);
 

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 32 - 16
src/main/java/com/shkpr/service/aimodelpower/globalmgr/ScheduleTaskMgr.java


+ 106 - 0
src/main/java/com/shkpr/service/aimodelpower/jsonbean/zilaishui/JPTbMMinutesWater.java

@@ -0,0 +1,106 @@
+package com.shkpr.service.aimodelpower.jsonbean.zilaishui;
+
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.aimodelpower.commtools.TimeTool;
+import com.shkpr.service.aimodelpower.controllervalid.CommonParamValidList;
+import com.shkpr.service.aimodelpower.controllervalid.CommonParamValidSS;
+import lombok.Data;
+import org.hibernate.validator.constraints.Range;
+import org.springframework.util.StringUtils;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAdjusters;
+
+/**
+ * @ClassName JPTbMHourWater
+ * @Description: TODO 查询日预测小时数据
+ * @Author LX
+ * @Date 2024/5/27
+ * @Version V1.0
+ **/
+@Data
+public class JPTbMMinutesWater {
+    private Boolean isPage = false;//是否分页 默认false
+
+    private String orgId;//水厂id
+
+    @Range(min = 0, max = 65535, groups = {CommonParamValidList.class, CommonParamValidSS.class})
+    private Integer limit = 20;//若分页 默认数为20
+
+    @Range(min = 0, max = Integer.MAX_VALUE, groups = {CommonParamValidList.class, CommonParamValidSS.class})
+    private Integer offset = 0;//若分页 默认起始值为0
+
+    private Long startDate;//开始日期 (实际时间为 年 月 日(就为当月的一号),时分秒为 00:00:00,如2023-03-01 00:00:00)
+
+    private Long endDate;//结束日期 (实际时间为 年 月 日(就为当月的一号),时分秒为 00:00:00,如2023-03-01 00:00:00)
+
+    //业务字段
+    private String forDateStr;
+
+    public boolean checkValid(){
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        StringBuilder strSql = new StringBuilder("");
+        if (!StringUtils.isEmpty(orgId)) {
+            strSql.append(" AND \"orgId\" = '" + orgId + "'");
+        }
+        if (startDate == null && endDate == null) {
+            //TODO 说明前端没传,那么默认为查今天0点到当前小时点的
+            LocalDateTime nowDate = LocalDateTime.now();//结束时间
+            nowDate = nowDate.withHour(0);
+            nowDate = nowDate.withMinute(0);
+            nowDate = nowDate.withSecond(0);
+
+            LocalDateTime startLocalDate = nowDate;
+
+            String startLocalDateStr = startLocalDate.format(formatter);
+            String endLocalDateStr = LocalDateTime.now().withMinute(0).withSecond(0).format(formatter);
+            String startLocalHourStr = startLocalDate.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
+            String endLocalHourStr = LocalDateTime.now().withMinute(0).withSecond(0).format(DateTimeFormatter.ofPattern("HH:mm:ss"));
+            strSql.append(" AND (\"Date\" || ' ' || \"Hour\")::timestamp BETWEEN  '" + startLocalDateStr+" " +startLocalHourStr+
+                    "' " + "AND '" + endLocalDateStr + " "+ endLocalHourStr + "'");
+            forDateStr = strSql.toString();
+        } else if (startDate != null && endDate != null) {
+            try {
+                LocalDateTime startLocalDate = LocalDateTime.parse(TimeTool.convertUTC2DateStr(startDate, TimeTool.TIMESTAMP_FORMAT), DateTimeFormatter.ofPattern(TimeTool.TIMESTAMP_FORMAT));
+                LocalDateTime endLocalDate = LocalDateTime.parse(TimeTool.convertUTC2DateStr(endDate, TimeTool.TIMESTAMP_FORMAT), DateTimeFormatter.ofPattern(TimeTool.TIMESTAMP_FORMAT));
+//                long monthsBetween = ChronoUnit.MONTHS.between(startLocalDate, endLocalDate);
+                if (startLocalDate.isAfter(endLocalDate)) {
+                    return false;
+                } else if (endLocalDate.isBefore(startLocalDate)) {
+                    return false;
+                } else if (startLocalDate.equals(endLocalDate) || startLocalDate.isBefore(endLocalDate)) {
+                    //TODO 说明符合可组成查询日期的条件
+                    //TODO 按照需求,特殊化结束时间再加4天
+                    String startLocalDateStr = startLocalDate.format(formatter);
+                    String endLocalDateStr = endLocalDate.format(formatter);
+                    String startLocalHourStr = startLocalDate.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
+                    String endLocalHourStr = endLocalDate.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
+                    strSql.append(" AND (\"Date\" || ' ' || \"Hour\")::timestamp BETWEEN  '" + startLocalDateStr+" " +startLocalHourStr+
+                            "' " + "AND '" + endLocalDateStr + " "+ endLocalHourStr + "'");
+                    forDateStr = strSql.toString();
+                }
+            } catch (Exception ex) {
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, "JPCustomerMeterSS", "JPCustomerMeterSS"
+                        , String.format("errorMsg:%s====>"
+                                , ex.getLocalizedMessage()));
+                return false;
+            }
+        } else if (startDate != null && endDate == null) {//警告没事,增加代码可读性
+            //TODO 说明startDate传了  endDate没传 , 那么endDate为startDate月的最后一天
+            LocalDateTime startLocalDate = LocalDateTime.parse(TimeTool.convertUTC2DateStr(startDate, TimeTool.TIMESTAMP_FORMAT), DateTimeFormatter.ofPattern(TimeTool.TIMESTAMP_FORMAT));
+            LocalDateTime endLocalDate =  LocalDateTime.now().withMinute(0).withSecond(0);
+            String startLocalDateStr = startLocalDate.format(formatter);
+            String endLocalDateStr = endLocalDate.format(formatter);
+            String startLocalHourStr = startLocalDate.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
+            String endLocalHourStr = endLocalDate.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
+            strSql.append(" AND (\"Date\" || ' ' || \"Hour\")::timestamp BETWEEN  '" + startLocalDateStr+" " +startLocalHourStr+
+                    "' " + "AND '" + endLocalDateStr + " "+ endLocalHourStr + "'");
+            forDateStr = strSql.toString();
+        }
+            return true;
+    }
+}

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 14 - 6
src/main/resources/application.properties