diff --git a/src/main/java/com/gunshi/project/hsz/controller/WaterAlarmController.java b/src/main/java/com/gunshi/project/hsz/controller/WaterAlarmController.java index 9074c39..43101e2 100644 --- a/src/main/java/com/gunshi/project/hsz/controller/WaterAlarmController.java +++ b/src/main/java/com/gunshi/project/hsz/controller/WaterAlarmController.java @@ -76,7 +76,7 @@ public class WaterAlarmController { return counts; } - @Operation(summary = "根据年份进行统计圆柱图") + @Operation(summary = "根据年份进行统计圆饼图") @GetMapping("/countTypeByYear") public List countTypeByYear(@RequestParam(value = "year") Integer year){ List res = service.countTypeByYear(year); diff --git a/src/main/java/com/gunshi/project/hsz/mapper/StWaterRMapper.java b/src/main/java/com/gunshi/project/hsz/mapper/StWaterRMapper.java index 586eeb0..bb33a92 100644 --- a/src/main/java/com/gunshi/project/hsz/mapper/StWaterRMapper.java +++ b/src/main/java/com/gunshi/project/hsz/mapper/StWaterRMapper.java @@ -28,4 +28,12 @@ public interface StWaterRMapper extends BaseMapper { """) List stat(@Param("obj") DateTimeRangeSo dateTimeRangeSo); + + @Select(""" + select t1.* from st_water_r t1 + join + (select stcd,max(tm) as max_tm from st_water_r GROUP BY stcd) t2 + on t1.stcd = t2.stcd and t1.tm = t2.max_tm ; +""") + List getStcdLastWaterData(); } \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/service/ReservoirWaterService.java b/src/main/java/com/gunshi/project/hsz/service/ReservoirWaterService.java index 170064d..7b411dc 100644 --- a/src/main/java/com/gunshi/project/hsz/service/ReservoirWaterService.java +++ b/src/main/java/com/gunshi/project/hsz/service/ReservoirWaterService.java @@ -120,6 +120,7 @@ public class ReservoirWaterService { } List zvarlList = stZvarlBService.list(); + zvarlList.sort(Comparator.comparing(StZvarlB::getRz)); voList.forEach(vo -> { if(vo.getCalState() == 1){ vo.setDesState(0); @@ -130,8 +131,8 @@ public class ReservoirWaterService { BigDecimal rz = vo.getRz(); if (rz != null) { - //TODO 这里可能也要更改一下水位-库容的计算方式,不能直接进行水库库容曲线的判断 - BigDecimal w = stZvarlBService.getWFromZvarl(rz, null, zvarlList); + //BigDecimal w = stZvarlBService.getWFromZvarl(rz, null, zvarlList); + BigDecimal w = stZvarlBService.getWByZvarl(zvarlList,rz); vo.setNowCap(w); } }); @@ -155,7 +156,7 @@ public class ReservoirWaterService { for (AttResBaseVo attResBaseVo : voList) { attResBaseVo.setIrrigationFlowSum(totalSum); } - //获取生态供水流量 + //获取新建生态供水流量站最新得流量 String ecologyStcd = "1114"; QueryWrapper ecologyQw = new QueryWrapper<>(); ecologyQw.eq("stcd", ecologyStcd).orderBy(true, false, "tm"); diff --git a/src/main/java/com/gunshi/project/hsz/service/StQxWarnRService.java b/src/main/java/com/gunshi/project/hsz/service/StQxWarnRService.java index be0eafe..810e0a7 100644 --- a/src/main/java/com/gunshi/project/hsz/service/StQxWarnRService.java +++ b/src/main/java/com/gunshi/project/hsz/service/StQxWarnRService.java @@ -125,6 +125,10 @@ public class StQxWarnRService extends ServiceImpl { vo.setOverRvUp("告警设置未配置,请检查"); }else{ BigDecimal rz = stRiverRReal.getZ(); + if(rz == null){ + vo.setOverRvUp("暂无最新水位数据"); + return; + } if(rz.compareTo(warnWaterLevel) >=0){ BigDecimal gap = rz.subtract(warnWaterLevel); vo.setOverRvUp("超警戒(" +gap.setScale(2, RoundingMode.HALF_UP)+")m"); @@ -148,8 +152,13 @@ public class StQxWarnRService extends ServiceImpl { BigDecimal promiseWaterLevel = alarmSet.getPromiseWaterLevel(); if(alarmSet == null){ vo.setOverRvDown("告警设置未配置,请检查"); + }else{ BigDecimal rz = stRiverRReal.getZ(); + if(rz == null){ + vo.setOverRvUp("暂无最新水位数据"); + return; + } if(rz.compareTo(warnWaterLevel) >=0){ BigDecimal gap = rz.subtract(warnWaterLevel); vo.setOverRvDown("超警戒(" +gap.setScale(2, RoundingMode.HALF_UP)+")m"); diff --git a/src/main/java/com/gunshi/project/hsz/service/StStbprpBService.java b/src/main/java/com/gunshi/project/hsz/service/StStbprpBService.java index 3071b5a..3961e01 100644 --- a/src/main/java/com/gunshi/project/hsz/service/StStbprpBService.java +++ b/src/main/java/com/gunshi/project/hsz/service/StStbprpBService.java @@ -23,8 +23,10 @@ import org.springframework.transaction.annotation.Transactional; import java.io.Serializable; import java.math.BigDecimal; +import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.time.Duration; +import java.time.Instant; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; @@ -138,13 +140,17 @@ public class StStbprpBService extends ServiceImpl { * 第一条数据的累计溢洪量设为0,第二条累计溢洪量=上一条累计溢洪量+本条溢洪流量*60分*60秒,以此类推 */ + //TODO 这里得确定一下,这个新建的泄洪道水位站是不是从水库历史水位表中查 + //获取水位历史数据 List rsvrList = rsvrRService.lambdaQuery() .eq(StRsvrR::getStcd, obj.getStcd()) .between(StRsvrR::getTm, obj.getDateSo().getStart(), obj.getDateSo().getEnd()) .orderBy(true, true, StRsvrR::getTm) .list(); + //查询水位-流量关系 List zqrlList = stZqrlBService.list(); zqrlList.sort(Comparator.comparing(StZqrlB::getZ)); + //获取水位-库容关系 List zvarlList = stZvarlBService.list(); zvarlList.sort(Comparator.comparing(StZvarlB::getRz)); List ret = new ArrayList<>(); @@ -156,34 +162,27 @@ public class StStbprpBService extends ServiceImpl { vo.setStcd(rsvr.getStcd()); vo.setTm(rsvr.getTm()); vo.setWaterLevel(rz); - - zqrlList.stream() - .filter(zqrl -> zqrl.getZ().equals(new BigDecimal(rsvr.getRz()))) - .findFirst() - .ifPresentOrElse(zqrl -> { - vo.setFlowNum(zqrl.getQ()); - }, () -> vo.setFlowNum(BigDecimal.ZERO)); - - zvarlList.stream() - .filter(zvarl -> zvarl.getRz().equals(new BigDecimal(rsvr.getRz()))) - .findFirst() - .ifPresentOrElse(zvarl -> { - vo.setBoxNum(zvarl.getW()); - }, () -> vo.setBoxNum(BigDecimal.ZERO)); - + //溢洪流量计算 + //TODO 这里水位->流量 需要计算公式 + BigDecimal q = stZqrlBService.getQByZqrl(zqrlList,rz);//根据水位计算流量 + vo.setFlowNum(q);//计算溢洪量(非累加值) + BigDecimal w = stZvarlBService.getWByZvarl(zvarlList, rz);//根据水位计算库容 + vo.setBoxNum(w); if (i == 0) { vo.setQtotal(BigDecimal.ZERO); } else { StZqrlBVo voPrev = ret.get(i - 1); - BigDecimal qTotal = vo.getFlowNum().multiply(BigDecimal.valueOf(60 * 60)); - BigDecimal prevQtotal = voPrev.getQtotal(); - qTotal = qTotal.add(prevQtotal); + //累计溢洪量 = 上一条数据累计溢洪量 + 本条溢洪流量 * 2条数据之间的间隔 + Instant curInstant = vo.getTm().toInstant(); + Instant preInstant = voPrev.getTm().toInstant(); + long timeDiffSeconds = Duration.between(curInstant, preInstant).getSeconds(); + + BigDecimal qTotal = voPrev.getQtotal().add(vo.getFlowNum().multiply(BigDecimal.valueOf(timeDiffSeconds))); vo.setQtotal(qTotal); } ret.add(vo); } - //倒序输出 ret.sort(Comparator.comparing(StZqrlBVo::getTm).reversed()); return ret; @@ -239,12 +238,11 @@ public class StStbprpBService extends ServiceImpl { complex.setRz(rz); complex.setTm(rsvr.getTm()); - //TODO 这里需要重新计算水位-流量对应数据 + //TODO 这里需要重新计算水位-流量(溢洪量)对应数据 //BigDecimal q = stZqrlBService.getQFromZqrl(rz, zqrlList); BigDecimal q = stZqrlBService.getQByZqrl(zqrlList,rz); complex.setQ(q); - //计算当前时间段溢洪量 - complex.setSv(complex.getQ().multiply(BigDecimal.valueOf(60 * 60))); + complex.setSv(complex.getQ()); // if (idx == 0) { // complex.setSv(BigDecimal.ZERO); // } else { @@ -261,46 +259,70 @@ public class StStbprpBService extends ServiceImpl { vo.setVal(complexList.getLast().getQ()); vo.setCreateTime(complexList.getLast().getTm()); - - //今日sv的和 - BigDecimal sumToday = complexList.stream().filter(complex -> complex.getTm().after(dayStart)) - .map(RsvrComplexVo::getSv) - .reduce(BigDecimal.ZERO, BigDecimal::add); + // 今日累计溢洪量(基于时间间隔的积分) + List complexDayList = complexList.stream().filter(complex -> complex.getTm().after(dayStart)).collect(Collectors.toList()); + BigDecimal sumToday = stZqrlBService.getFlowQSum(complexDayList); vo.setCurrDayValSum(sumToday); - // 当月溢洪量总和(筛选本月数据) - BigDecimal sumMonth = complexList.stream() - .filter(complex -> (complex.getTm().after(monthStart) || complex.getTm().equals(monthStart)) - && complex.getTm().before(now) || complex.getTm().equals(now)) - .map(RsvrComplexVo::getSv) - .reduce(BigDecimal.ZERO, BigDecimal::add); + + // 当月累计溢洪量 + List complexMonthList = complexList.stream().filter(complex -> (complex.getTm().after(monthStart) || complex.getTm().equals(monthStart)) + && complex.getTm().before(now) || complex.getTm().equals(now)).collect(Collectors.toList()); + BigDecimal sumMonth = stZqrlBService.getFlowQSum(complexMonthList); vo.setCurrMonthSum(sumMonth); - // 当年溢洪量总和(所有数据都是当年的,直接求和) - BigDecimal sumYear = complexList.stream() - .map(RsvrComplexVo::getSv) - .reduce(BigDecimal.ZERO, BigDecimal::add); + + + // 当年累计溢洪量 + BigDecimal sumYear = stZqrlBService.getFlowQSum(complexList); vo.setCurrYearSum(sumYear); - // 计算本年溢洪次数(溢洪量>0) - long overflowCount = complexList.stream() - .filter(complex -> complex.getSv().compareTo(BigDecimal.ZERO) > 0) - .count(); - vo.setCurrYearCount(overflowCount); +// //今日sv的和 +// BigDecimal sumToday = complexList.stream().filter(complex -> complex.getTm().after(dayStart)) +// .map(RsvrComplexVo::getSv) +// .reduce(BigDecimal.ZERO, BigDecimal::add); +// vo.setCurrDayValSum(sumToday); +// +// // 当月溢洪量总和(筛选本月数据) +// BigDecimal sumMonth = complexList.stream() +// .filter(complex -> (complex.getTm().after(monthStart) || complex.getTm().equals(monthStart)) +// && complex.getTm().before(now) || complex.getTm().equals(now)) +// .map(RsvrComplexVo::getSv) +// .reduce(BigDecimal.ZERO, BigDecimal::add); +// vo.setCurrMonthSum(sumMonth); +// +// // 当年溢洪量总和(所有数据都是当年的,直接求和) +// BigDecimal sumYear = complexList.stream() +// .map(RsvrComplexVo::getSv) +// .reduce(BigDecimal.ZERO, BigDecimal::add); +// vo.setCurrYearSum(sumYear); + //计算溢洪次数 + // 0 0 0 1 1 0 1 0 1 + int overFlowCount = 0; + boolean isOverFlow = false; + //连续的sv > 0 才算一次 溢洪 + for(int i =0;i 0){ + if(!isOverFlow){ + overFlowCount++; + isOverFlow = true; + } + }else{ + isOverFlow = false; + } + } + vo.setCurrYearCount(Long.valueOf(overFlowCount)); // 本年单次最大溢洪量 Optional maxOverflowComplex = complexList.stream() .max(Comparator.comparing(RsvrComplexVo::getSv)); if (maxOverflowComplex.isPresent()) { RsvrComplexVo maxComplex = maxOverflowComplex.get(); vo.setCurrYearMaxVal(maxComplex.getSv()); - - // 假设最大溢洪量持续了一段时间(这里需要根据业务逻辑确定) - // 简单处理:显示发生时间 SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm:ss"); - // 如果需要更复杂的时间段计算,可以根据前后数据点来判断 int maxIndex = complexList.indexOf(maxComplex); if (maxIndex < complexList.size() - 1) { // 可以取前后时间点作为时间段的参考 @@ -317,12 +339,6 @@ public class StStbprpBService extends ServiceImpl { vo.setCurrYearMaxVal(BigDecimal.ZERO); vo.setMaxOverflowPeriod("无溢洪记录"); } -// BigDecimal maxOverflow = complexList.stream() -// .map(RsvrComplexVo::getSv) -// .max(Comparator.naturalOrder()) -// .orElse(BigDecimal.ZERO); -// vo.setCurrYearMaxVal(maxOverflow); - return vo; } @@ -335,14 +351,19 @@ public class StStbprpBService extends ServiceImpl { return vo; } BigDecimal rzLatest = new BigDecimal(rsvrLatest.getRz()); - BigDecimal qLatest = stZqrlBService.getQFromZqrl(rzLatest); + //获取水位-流量数据k + List zqrlBList = stZqrlBService.list(); + //TODO 转换溢洪流量计算 + BigDecimal qLatest = stZqrlBService.getQByZqrl(zqrlBList,rzLatest); + //BigDecimal qLatest = stZqrlBService.getQFromZqrl(rzLatest); vo.setCurrWaterLevel(rzLatest); - vo.setFlowNum(qLatest); + vo.setFlowNum(qLatest);//当前溢洪量 就为 流量 vo.setCreateTime(rsvrLatest.getTm()); LocalDateTime now = LocalDateTime.now(); LocalDateTime before24 = now.minusHours(24); List rsvrList = rsvrRService.lambdaQuery().ge(StRsvrR::getTm, before24).le(StRsvrR::getTm, now).orderByAsc(StRsvrR::getTm).list(); + //TODO 这个溢洪流量汇总的计算也需要进行公式计算 List rsvrComplexVos = stZqrlBService.calculateSpilledVolumeList(rsvrList); BigDecimal totalSv = rsvrComplexVos.stream().map(RsvrComplexVo::getSv).reduce(BigDecimal.ZERO, BigDecimal::add); vo.setSum24(totalSv); diff --git a/src/main/java/com/gunshi/project/hsz/service/StWaterRService.java b/src/main/java/com/gunshi/project/hsz/service/StWaterRService.java index 542b814..78dc5d3 100644 --- a/src/main/java/com/gunshi/project/hsz/service/StWaterRService.java +++ b/src/main/java/com/gunshi/project/hsz/service/StWaterRService.java @@ -29,6 +29,10 @@ public class StWaterRService extends ServiceImpl return list.stream() .collect(Collectors.groupingBy(StWaterR::getStcd, Collectors.mapping(StWaterR::getV, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)))); } + + public List getStcdLastWaterData() { + return this.baseMapper.getStcdLastWaterData(); + } } diff --git a/src/main/java/com/gunshi/project/hsz/service/StZqrlBService.java b/src/main/java/com/gunshi/project/hsz/service/StZqrlBService.java index 21b969a..8a8e112 100644 --- a/src/main/java/com/gunshi/project/hsz/service/StZqrlBService.java +++ b/src/main/java/com/gunshi/project/hsz/service/StZqrlBService.java @@ -11,6 +11,7 @@ import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.math.RoundingMode; +import java.time.Duration; import java.util.*; import java.util.stream.Collectors; @@ -65,7 +66,8 @@ public class StZqrlBService extends ServiceImpl { BigDecimal rz = new BigDecimal(rsvr.getRz()); Date tm = rsvr.getTm(); RsvrComplexVo vo = RsvrComplexVo.of(rz, tm); - + BigDecimal q = getQFromZqrl(rz, zqrlList); + //TODO 这个需要公式进行对水位->流量的转换 if (i == 0) { vo.setQ(getQFromZqrl(rz, zqrlList)); vo.setSv(BigDecimal.ZERO); @@ -74,6 +76,7 @@ public class StZqrlBService extends ServiceImpl { Date tmPrev = rsvrPrev.getTm(); long seconds = tm.getTime() - tmPrev.getTime(); vo.setQ(getQFromZqrl(rz, zqrlList)); + //TODO 这里有个函数调用,记得到时候也替换一下计算公式 vo.setSv(calculateSpilledVolume(rz, seconds)); } ret.add(vo); @@ -128,6 +131,104 @@ public class StZqrlBService extends ServiceImpl { .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } + public BigDecimal getQByZqrl(List zqrlBList, BigDecimal rz) { + int l =0; + int r = zqrlBList.size() - 1; + if(rz.compareTo(zqrlBList.get(0).getZ()) < 0){ + return BigDecimal.ZERO; + } + //使用二分法,来获取 避免On的查询时间复杂度 + while(l < r){ + int mid = l + (r - l) / 2; + if(zqrlBList.get(mid).getZ().compareTo(rz) ==0){ + return zqrlBList.get(mid).getQ(); + }else if(zqrlBList.get(mid).getZ().compareTo(rz) >0){ + r = mid - 1; + }else{ + l = mid + 1; + } + } + + // 现在 l 是最接近的索引,但需要比较前后三个值 + int closestIndex = l; + + // 处理边界情况 + if (l == 0) { + // 只有第一个元素,或者比较第一个和第二个哪个更接近 + if (zqrlBList.size() > 1) { + BigDecimal diff1 = rz.subtract(zqrlBList.get(0).getZ()).abs(); + BigDecimal diff2 = rz.subtract(zqrlBList.get(1).getZ()).abs(); + closestIndex = diff1.compareTo(diff2) <= 0 ? 0 : 1; + } + //TODO 这里找到最接近的值后,仍然要通过公式,计算出真正的流量 + return zqrlBList.get(closestIndex).getQ(); + } + + if (l == zqrlBList.size() - 1) { + // 只有最后一个元素,或者比较最后两个哪个更接近 + if (zqrlBList.size() > 1) { + BigDecimal diff1 = rz.subtract(zqrlBList.get(l - 1).getZ()).abs(); + BigDecimal diff2 = rz.subtract(zqrlBList.get(l).getZ()).abs(); + closestIndex = diff1.compareTo(diff2) <= 0 ? l - 1 : l; + } + //TODO 这里找到最接近的值后,仍然要通过公式,计算出真正的流量 + return zqrlBList.get(closestIndex).getQ(); + } + + // 正常情况:比较前一个、当前、后一个三个值,找到最接近的 + BigDecimal preVal = zqrlBList.get(l - 1).getZ(); + BigDecimal curVal = zqrlBList.get(l).getZ(); + BigDecimal nextVal = zqrlBList.get(l + 1).getZ(); + + //计算他们与目标的插值 + BigDecimal diffPre = rz.subtract(preVal).abs(); + BigDecimal diffCur = rz.subtract(curVal).abs(); + BigDecimal diffNext = rz.subtract(nextVal).abs(); + + // 找到最小的差值 + if (diffPre.compareTo(diffCur) <= 0 && diffPre.compareTo(diffNext) <= 0) { + closestIndex = l - 1; + } else if (diffCur.compareTo(diffPre) <= 0 && diffCur.compareTo(diffNext) <= 0) { + closestIndex = l; + } else { + closestIndex = l + 1; + } + + //TODO 这里找到最接近的值后,仍然要通过公式,计算出真正的流量 + + return zqrlBList.get(closestIndex).getQ(); + } + + /** + * 计算累计溢洪量 + * @param complexList + * @return + */ + public BigDecimal getFlowQSum(List complexList) { + BigDecimal sum = BigDecimal.ZERO; + for (int i = 0; i < complexList.size(); i++) { + RsvrComplexVo current = complexList.get(i); + if (i == 0) { + // 第一条数据,累计量为0 + sum = BigDecimal.ZERO; + } else { + RsvrComplexVo previous = complexList.get(i - 1); + + // 计算时间间隔(秒) + long timeDiffSeconds = Duration.between(previous.getTm().toInstant(), + current.getTm().toInstant()).getSeconds(); + + if (timeDiffSeconds > 0) { + // 使用梯形法则计算这段时间内的溢洪量:(上一个流量 + 当前流量) / 2 * 时间间隔 + BigDecimal avgFlow = previous.getSv().add(current.getSv()) + .divide(BigDecimal.valueOf(2), 10, RoundingMode.HALF_UP); + BigDecimal increment = avgFlow.multiply(BigDecimal.valueOf(timeDiffSeconds)); + sum = sum.add(increment); + } + } + } + return sum; + } } diff --git a/src/main/java/com/gunshi/project/hsz/timetask/DataTaskHsz.java b/src/main/java/com/gunshi/project/hsz/timetask/DataTaskHsz.java index 8081e49..a73d86d 100644 --- a/src/main/java/com/gunshi/project/hsz/timetask/DataTaskHsz.java +++ b/src/main/java/com/gunshi/project/hsz/timetask/DataTaskHsz.java @@ -6,27 +6,15 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.gunshi.project.hsz.model.StPptnR; -import com.gunshi.project.hsz.model.StPptnRD; -import com.gunshi.project.hsz.model.StPptnRH; -import com.gunshi.project.hsz.model.StRiverR; -import com.gunshi.project.hsz.model.StRiverRReal; -import com.gunshi.project.hsz.model.StRsvrR; -import com.gunshi.project.hsz.model.StRsvrRReal; -import com.gunshi.project.hsz.service.StPptnRDService; -import com.gunshi.project.hsz.service.StPptnRHService; -import com.gunshi.project.hsz.service.StPptnRRealService; -import com.gunshi.project.hsz.service.StPptnRService; -import com.gunshi.project.hsz.service.StRiverRRealService; -import com.gunshi.project.hsz.service.StRiverRService; -import com.gunshi.project.hsz.service.StRsvrRRealService; -import com.gunshi.project.hsz.service.StRsvrRService; +import com.gunshi.project.hsz.model.*; +import com.gunshi.project.hsz.service.*; import com.gunshi.project.hsz.util.OkHttpUtil; import lombok.extern.slf4j.Slf4j; import okhttp3.FormBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; +import org.checkerframework.checker.units.qual.A; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -40,9 +28,11 @@ import java.io.IOException; import java.math.BigDecimal; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.List; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.*; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Collectors; @@ -80,6 +70,8 @@ public class DataTaskHsz { public static String jcskPathRrRiverRoute = "/river/";// ZZ河道水位接口 public static String jcskPathZzRsvrRoute = "/rsvr/";// RR水库水位接口 + public static String jcskPathWaterRRoute = "";//供水接口 + // 实时雨情 @Autowired private StPptnRRealService stPptnRRealService; @@ -112,6 +104,18 @@ public class DataTaskHsz { @Autowired private StRiverRService stRiverRService; + //历史供水量 + @Autowired + private StWaterRService stWaterRService; + + //实时供水量 + @Autowired + private StWaterRRealService stWaterRRealService; + + //供水量整编 + @Autowired + private StWaterRReorganizeService stWaterRReorganizeService; + /** * @param * @description: 定时获取水库雨情数据(历史、天、时、real) @@ -236,6 +240,149 @@ public class DataTaskHsz { } } + /** + * 定时获取供水量数据 + */ + //@Async + //@Scheduled(fixedRate = 70 , timeUnit = TimeUnit.MINUTES) + public void getWaterData(){ + Date now = new Date(); + System.out.println("供水量定时任务,执行时间:" + sdf.format(now)); + //获取供水量站点表中 每个站点的最新数据时间 + List stcdLast = stWaterRService.getStcdLastWaterData(); + OkHttpClient client = OkHttpUtil.build(); + String stcd1 = "";//干渠灌溉1 + String stcd2 = "";//干渠灌溉2 + String ecoStcd = "";//生态供水 + try { + if(ObjectUtils.isNotEmpty(stcdLast)){ + //对每个数据进行遍历 + for (StWaterR stWaterR : stcdLast) { + Date stm = stWaterR.getTm(); + Calendar calendar = Calendar.getInstance(); + if(ObjectUtils.isEmpty(stm)){ + //如果从来没有数据 + calendar.add(Calendar.DATE, -30); + }else{ + //同步过数据 + int diffDays = new BigDecimal((int) Math.ceil((now.getTime() - stm.getTime()) / (24 * 60 * 60 * 1000))).intValue(); + if (diffDays > 3) { + //如果时间差大于3天 + calendar.add(Calendar.DATE, -2); + calendar.add(Calendar.HOUR_OF_DAY, -20); + } else { + //小于三天 + calendar.setTime(stm); + calendar.add(Calendar.MINUTE, 1); + } + } + stm = calendar.getTime(); + //构建url + //TODO 这里还需要根据实际url来进行更改 + String url = jcskPath; + String waterRSource = ""; + url += jcskPathWaterRRoute + waterRSource; + //构建HTTP请求 + Response resp = client.newCall(new Request.Builder().url(url) + .post(new FormBody.Builder().add("stcd", stWaterR.getStcd()) + .add("stm", sdf.format(stm)) + .add("etm", sdf.format(now)) + .build()) + .header("Token", jcskToken) + .addHeader("Content-Type", "application/x-www-form-urlencoded") + .build()).execute(); + String respStr = resp.body().string(); + JSONObject jsonObject = JSONObject.parseObject(respStr.toLowerCase()); + if (!"200".equals(jsonObject.get("code").toString())) { + continue; + } + JSONArray data = jsonObject.getJSONArray("data"); + if(CollectionUtils.isNotEmpty(data)){ + List rList = data.toJavaList(StWaterR.class); + stWaterRService.saveBatch(rList); + //更新实时数据表 + StWaterR stWaterRLast = rList.get(rList.size() - 1); + StWaterRReal stWaterRReal = new StWaterRReal(); + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.set("stcd", stWaterR.getStcd()) + .eq("tm",stWaterRLast.getTm()); + BeanUtils.copyProperties(stWaterRLast, stWaterRReal); + stWaterRRealService.saveOrUpdate(stWaterRReal); + //同步至供水整编表中 + // 使用 DateTimeFormatter(线程安全) + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH"); + Map> groupedByTime = rList.stream() + .collect(Collectors.groupingBy(waterR -> { + try { + Instant instant = waterR.getTm().toInstant(); + LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); + return localDateTime.format(formatter); + } catch (Exception e) { + return "未知时间"; + } + })); + + // 组装数据并保存 + List reorganizeList = new ArrayList<>(); + for (Map.Entry> entry : groupedByTime.entrySet()) { + String timeKey = entry.getKey(); + List timeData = entry.getValue(); + + StWaterRReorganize reorganize = new StWaterRReorganize(); + reorganize.setTm(timeKey); + + // 初始化各字段为0 + reorganize.setEcologyQ(BigDecimal.ZERO); + reorganize.setEcologyV(BigDecimal.ZERO); + reorganize.setMci1Q(BigDecimal.ZERO); + reorganize.setMci1V(BigDecimal.ZERO); + reorganize.setMci2Q(BigDecimal.ZERO); + reorganize.setMci2V(BigDecimal.ZERO); + reorganize.setSumV(BigDecimal.ZERO); + + // 按站点类型处理数据 + for (StWaterR waterR : timeData) { + String stcd = waterR.getStcd(); + BigDecimal q = waterR.getQ(); + BigDecimal v = waterR.getV(); + + if (ecoStcd.equals(stcd)) { + // 生态供水数据 + reorganize.setEcologyQ(q); + reorganize.setEcologyV(v); + } else if (stcd1.equals(stcd)) { + // 干渠灌溉1数据 + reorganize.setMci1Q(q); + reorganize.setMci1V(v); + } else if (stcd2.equals(stcd)) { + // 干渠灌溉2数据 + reorganize.setMci2Q(q); + reorganize.setMci2V(v); + } + } + + // 计算水量小计 + BigDecimal sumV = reorganize.getEcologyV() + .add(reorganize.getMci1V()) + .add(reorganize.getMci2V()); + reorganize.setSumV(sumV); + + reorganizeList.add(reorganize); + } + + // 批量保存到重组表 + if (!reorganizeList.isEmpty()) { + stWaterRReorganizeService.saveBatch(reorganizeList); + System.out.println("成功同步 " + reorganizeList.size() + " 条数据到重组表"); + } + } + } + } + }catch (Exception e){ + log.error("供水历史定时任务错误:", e.getMessage()); + } + } + /** * @description: 定时获取水库水情数据(历史、real) * @param @@ -243,8 +390,8 @@ public class DataTaskHsz { * @auther: cxw * @date: 2024-09-23, 周一, 11:23:04 */ - @Async - @Scheduled(fixedRate = 5, timeUnit = TimeUnit.MINUTES) + //@Async + //@Scheduled(fixedRate = 5, timeUnit = TimeUnit.MINUTES) public void getRiverData() { Date now = new Date(); System.out.println("水情历史定时任务,执行时间:" + sdf.format(now)); @@ -253,6 +400,7 @@ public class DataTaskHsz { OkHttpClient client = OkHttpUtil.build(); try { if (CollectionUtils.isNotEmpty(stcdLast)) { + //对每个数据进行遍历 for (StRsvrR stRsvrR : stcdLast) { Date stm = stRsvrR.getStm(); String source = stRsvrR.getSource().toLowerCase(); @@ -261,18 +409,24 @@ public class DataTaskHsz { // 默认40天前(接口最多40天),存在则加1小时(接口是按小时算且大于等于开始时间) // 默认30天前 if (ObjectUtils.isEmpty(stm)) { + //如果数据库中没有该站点任何时间得数据 if ("sh".equals(source)) { + //对于sh源得数据,取前30天至今 calendar.add(Calendar.DATE, -30); } else { + //其它源得数据,取前2天20小时 calendar.add(Calendar.DATE, -2); calendar.add(Calendar.HOUR_OF_DAY, -20); } } else { + //如果又时间,则计算当前时间与最后一次同步得时间差 int diffDays = new BigDecimal((int) Math.ceil((now.getTime() - stm.getTime()) / (24 * 60 * 60 * 1000))).intValue(); if (diffDays > 3) { + //如果时间差大于3天 calendar.add(Calendar.DATE, -2); calendar.add(Calendar.HOUR_OF_DAY, -20); } else { + //小于三天 calendar.setTime(stm); calendar.add(Calendar.MINUTE, 1); } @@ -290,6 +444,7 @@ public class DataTaskHsz { continue; } } + //构建HTTP请求 Response resp = client.newCall(new Request.Builder().url(url) .post(new FormBody.Builder().add("stcd", stRsvrR.getStcd()) .add("stm", sdf.format(stm)) @@ -305,6 +460,7 @@ public class DataTaskHsz { } JSONArray data = jsonObject.getJSONArray("data"); if (CollectionUtils.isNotEmpty(data)) { + //如果是zz类型站得数据 if ("zz".equals(sttp)) { List rlist = data.toJavaList(StRiverR.class); stRiverRService.saveBatch(rlist); diff --git a/src/main/resources/mapper/StWaterRRealMapper.xml b/src/main/resources/mapper/StWaterRRealMapper.xml index 94b2de5..cf463c6 100644 --- a/src/main/resources/mapper/StWaterRRealMapper.xml +++ b/src/main/resources/mapper/StWaterRRealMapper.xml @@ -18,8 +18,9 @@ GROUP BY stcd ) latest ON t.stcd = latest.stcd AND t.tm = latest.max_tm - stb.sttp in ('QQ', 'PQ') - and stb.stcd in ('1112','1113','1114') -- 站点编码,这里到时候得改 + + + and stb.stcd in ('1112','1113','1114')