水位-流量的计算(还需要等待计算公式)

供水定时任务(需要等待接口的信息)
master
yangzhe123 2025-09-16 14:25:13 +08:00
parent 0bc0259e02
commit 086c405ff6
9 changed files with 382 additions and 81 deletions

View File

@ -76,7 +76,7 @@ public class WaterAlarmController {
return counts;
}
@Operation(summary = "根据年份进行统计圆图")
@Operation(summary = "根据年份进行统计圆图")
@GetMapping("/countTypeByYear")
public List<WaterAlarmTypeCount> countTypeByYear(@RequestParam(value = "year") Integer year){
List<WaterAlarmTypeCount> res = service.countTypeByYear(year);

View File

@ -28,4 +28,12 @@ public interface StWaterRMapper extends BaseMapper<StWaterR> {
</script>
""")
List<StWaterR> 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<StWaterR> getStcdLastWaterData();
}

View File

@ -120,6 +120,7 @@ public class ReservoirWaterService {
}
List<StZvarlB> 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<StWaterRReal> ecologyQw = new QueryWrapper<>();
ecologyQw.eq("stcd", ecologyStcd).orderBy(true, false, "tm");

View File

@ -125,6 +125,10 @@ public class StQxWarnRService extends ServiceImpl<StQxWarnRMapper, StQxWarnR> {
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<StQxWarnRMapper, StQxWarnR> {
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");

View File

@ -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<StStbprpBMapper, StStbprpB> {
* 0=+*60*60
*/
//TODO 这里得确定一下,这个新建的泄洪道水位站是不是从水库历史水位表中查
//获取水位历史数据
List<StRsvrR> rsvrList = rsvrRService.lambdaQuery()
.eq(StRsvrR::getStcd, obj.getStcd())
.between(StRsvrR::getTm, obj.getDateSo().getStart(), obj.getDateSo().getEnd())
.orderBy(true, true, StRsvrR::getTm)
.list();
//查询水位-流量关系
List<StZqrlB> zqrlList = stZqrlBService.list();
zqrlList.sort(Comparator.comparing(StZqrlB::getZ));
//获取水位-库容关系
List<StZvarlB> zvarlList = stZvarlBService.list();
zvarlList.sort(Comparator.comparing(StZvarlB::getRz));
List<StZqrlBVo> ret = new ArrayList<>();
@ -156,34 +162,27 @@ public class StStbprpBService extends ServiceImpl<StStbprpBMapper, StStbprpB> {
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<StStbprpBMapper, StStbprpB> {
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<StStbprpBMapper, StStbprpB> {
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<RsvrComplexVo> 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<RsvrComplexVo> 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<complexList.size();i++){
BigDecimal sv = complexList.get(i).getSv();
if(sv.compareTo(BigDecimal.ZERO) > 0){
if(!isOverFlow){
overFlowCount++;
isOverFlow = true;
}
}else{
isOverFlow = false;
}
}
vo.setCurrYearCount(Long.valueOf(overFlowCount));
// 本年单次最大溢洪量
Optional<RsvrComplexVo> 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<StStbprpBMapper, StStbprpB> {
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<StStbprpBMapper, StStbprpB> {
return vo;
}
BigDecimal rzLatest = new BigDecimal(rsvrLatest.getRz());
BigDecimal qLatest = stZqrlBService.getQFromZqrl(rzLatest);
//获取水位-流量数据k
List<StZqrlB> 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<StRsvrR> rsvrList = rsvrRService.lambdaQuery().ge(StRsvrR::getTm, before24).le(StRsvrR::getTm, now).orderByAsc(StRsvrR::getTm).list();
//TODO 这个溢洪流量汇总的计算也需要进行公式计算
List<RsvrComplexVo> rsvrComplexVos = stZqrlBService.calculateSpilledVolumeList(rsvrList);
BigDecimal totalSv = rsvrComplexVos.stream().map(RsvrComplexVo::getSv).reduce(BigDecimal.ZERO, BigDecimal::add);
vo.setSum24(totalSv);

View File

@ -29,6 +29,10 @@ public class StWaterRService extends ServiceImpl<StWaterRMapper, StWaterR>
return list.stream()
.collect(Collectors.groupingBy(StWaterR::getStcd, Collectors.mapping(StWaterR::getV, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
}
public List<StWaterR> getStcdLastWaterData() {
return this.baseMapper.getStcdLastWaterData();
}
}

View File

@ -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<StZqrlBMapper, StZqrlB> {
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<StZqrlBMapper, StZqrlB> {
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<StZqrlBMapper, StZqrlB> {
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
public BigDecimal getQByZqrl(List<StZqrlB> 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<RsvrComplexVo> 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;
}
}

View File

@ -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<StWaterR> 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<StWaterR> rList = data.toJavaList(StWaterR.class);
stWaterRService.saveBatch(rList);
//更新实时数据表
StWaterR stWaterRLast = rList.get(rList.size() - 1);
StWaterRReal stWaterRReal = new StWaterRReal();
UpdateWrapper<StWaterRReal> 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<String, List<StWaterR>> 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<StWaterRReorganize> reorganizeList = new ArrayList<>();
for (Map.Entry<String, List<StWaterR>> entry : groupedByTime.entrySet()) {
String timeKey = entry.getKey();
List<StWaterR> 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<StRiverR> rlist = data.toJavaList(StRiverR.class);
stRiverRService.saveBatch(rlist);

View File

@ -18,8 +18,9 @@
GROUP BY stcd
) latest ON t.stcd = latest.stcd AND t.tm = latest.max_tm
<where>
stb.sttp in ('QQ', 'PQ')
and stb.stcd in ('1112','1113','1114') -- 站点编码,这里到时候得改
<!-- stb.sttp in ('QQ', 'PQ','ZI') 站点类型 站点编码是唯一的,所以不用对类型进行 -->
and stb.stcd in ('1112','1113','1114') <!-- 站点编码 -->
</where>
</select>